Merge branch 'blender2.7' of git.blender.org:blender
[blender.git] / doc / python_api / rst / info_gotcha.rst
1
2 *******
3 Gotchas
4 *******
5
6 This document attempts to help you work with the Blender API in areas
7 that can be troublesome and avoid practices that are known to give instability.
8
9
10 .. _using_operators:
11
12 Using Operators
13 ===============
14
15 Blender's operators are tools for users to access, that Python can access them too is very useful
16 nevertheless operators have limitations that can make them cumbersome to script.
17
18 Main limits are...
19
20 - Can't pass data such as objects, meshes or materials to operate on (operators use the context instead)
21 - The return value from calling an operator gives the success (if it finished or was canceled),
22   in some cases it would be more logical from an API perspective to return the result of the operation.
23 - Operators poll function can fail where an API function would raise an exception giving details on exactly why.
24
25
26 Why does an operator's poll fail?
27 ---------------------------------
28
29 When calling an operator gives an error like this:
30
31    >>> bpy.ops.action.clean(threshold=0.001)
32    RuntimeError: Operator bpy.ops.action.clean.poll() failed, context is incorrect
33
34 Which raises the question as to what the correct context might be?
35
36 Typically operators check for the active area type, a selection or active object they can operate on,
37 but some operators are more picky about when they run.
38
39 In most cases you can figure out what context an operator needs
40 simply be seeing how it's used in Blender and thinking about what it does.
41
42 Unfortunately if you're still stuck - the only way to **really** know
43 whats going on is to read the source code for the poll function and see what its checking.
44
45 For Python operators it's not so hard to find the source
46 since it's included with Blender and the source file/line is included in the operator reference docs.
47
48 Downloading and searching the C code isn't so simple,
49 especially if you're not familiar with the C language but by searching the
50 operator name or description you should be able to find the poll function with no knowledge of C.
51
52 .. note::
53
54    Blender does have the functionality for poll functions to describe why they fail,
55    but its currently not used much, if you're interested to help improve our API
56    feel free to add calls to ``CTX_wm_operator_poll_msg_set`` where its not obvious why poll fails.
57
58       >>> bpy.ops.gpencil.draw()
59       RuntimeError: Operator bpy.ops.gpencil.draw.poll() Failed to find Grease Pencil data to draw into
60
61
62 The operator still doesn't work!
63 --------------------------------
64
65 Certain operators in Blender are only intended for use in a specific context,
66 some operators for example are only called from the properties window where they check the current material,
67 modifier or constraint.
68
69 Examples of this are:
70
71 - :mod:`bpy.ops.texture.slot_move`
72 - :mod:`bpy.ops.constraint.limitdistance_reset`
73 - :mod:`bpy.ops.object.modifier_copy`
74 - :mod:`bpy.ops.buttons.file_browse`
75
76 Another possibility is that you are the first person to attempt to use this operator
77 in a script and some modifications need to be made to the operator to run in a different context,
78 if the operator should logically be able to run but fails when accessed from a script
79 it should be reported to the bug tracker.
80
81
82 Stale Data
83 ==========
84
85 No updates after setting values
86 -------------------------------
87
88 Sometimes you want to modify values from Python and immediately access the updated values, eg:
89
90 Once changing the objects :class:`bpy.types.Object.location`
91 you may want to access its transformation right after from :class:`bpy.types.Object.matrix_world`,
92 but this doesn't work as you might expect.
93
94 Consider the calculations that might go into working out the object's final transformation, this includes:
95
96 - animation function curves.
97 - drivers and their Python expressions.
98 - constraints
99 - parent objects and all of their f-curves, constraints etc.
100
101 To avoid expensive recalculations every time a property is modified,
102 Blender defers making the actual calculations until they are needed.
103
104 However, while the script runs you may want to access the updated values.
105 In this case you need to call :class:`bpy.types.Scene.update` after modifying values, for example:
106
107 .. code-block:: python
108
109    bpy.context.object.location = 1, 2, 3
110    bpy.context.scene.update()
111
112
113 Now all dependent data (child objects, modifiers, drivers... etc)
114 has been recalculated and is available to the script.
115
116
117 Can I redraw during the script?
118 -------------------------------
119
120 The official answer to this is no, or... *"You don't want to do that"*.
121
122 To give some background on the topic...
123
124 While a script executes Blender waits for it to finish and is effectively locked until its done,
125 while in this state Blender won't redraw or respond to user input.
126 Normally this is not such a problem because scripts distributed with Blender
127 tend not to run for an extended period of time,
128 nevertheless scripts *can* take ages to execute and its nice to see whats going on in the view port.
129
130 Tools that lock Blender in a loop and redraw are highly discouraged
131 since they conflict with Blenders ability to run multiple operators
132 at once and update different parts of the interface as the tool runs.
133
134 So the solution here is to write a **modal** operator, that is - an operator which defines a modal() function,
135 See the modal operator template in the text  editor.
136
137 Modal operators execute on user input or setup their own timers to run frequently,
138 they can handle the events or pass through to be handled by the keymap or other modal operators.
139
140 Transform, Painting, Fly-Mode and File-Select are example of a modal operators.
141
142 Writing modal operators takes more effort than a simple ``for`` loop
143 that happens to redraw but is more flexible and integrates better with Blenders design.
144
145
146 **Ok, Ok! I still want to draw from Python**
147
148 If you insist - yes its possible, but scripts that use this hack won't be considered
149 for inclusion in Blender and any issues with using it won't be considered bugs,
150 this is also not guaranteed to work in future releases.
151
152 .. code-block:: python
153
154    bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
155
156
157 Modes and Mesh Access
158 =====================
159
160 When working with mesh data you may run into the problem where a script fails to run as expected in edit-mode.
161 This is caused by edit-mode having its own data which is only written back to the mesh when exiting edit-mode.
162
163 A common example is that exporters may access a mesh through ``obj.data`` (a :class:`bpy.types.Mesh`)
164 but the user is in edit-mode, where the mesh data is available but out of sync with the edit mesh.
165
166 In this situation you can...
167
168 - Exit edit-mode before running the tool.
169 - Explicitly update the mesh by calling :class:`bmesh.types.BMesh.to_mesh`.
170 - Modify the script to support working on the edit-mode data directly, see: :mod:`bmesh.from_edit_mesh`.
171 - Report the context as incorrect and only allow the script to run outside edit-mode.
172
173
174 .. _info_gotcha_mesh_faces:
175
176 N-Gons and Tessellation
177 =======================
178
179 Since 2.63 NGons are supported, this adds some complexity
180 since in some cases you need to access triangles still (some exporters for example).
181
182 There are now 3 ways to access faces:
183
184 - :class:`bpy.types.MeshPolygon` -
185   this is the data structure which now stores faces in object mode
186   (access as ``mesh.polygons`` rather than ``mesh.faces``).
187 - :class:`bpy.types.MeshLoopTriangle` -
188   the result of tessellating polygons into triangles
189   (access as ``mesh.loop_triangles``).
190 - :class:`bmesh.types.BMFace` -
191   the polygons as used in editmode.
192
193 For the purpose of the following documentation,
194 these will be referred to as polygons, loop triangles and bmesh-faces respectively.
195
196 5+ sided faces will be referred to as ``ngons``.
197
198
199 Support Overview
200 ----------------
201
202 .. list-table::
203    :header-rows: 1
204    :stub-columns: 1
205
206    * - Usage
207      - :class:`bpy.types.MeshPolygon`
208      - :class:`bpy.types.MeshTessFace`
209      - :class:`bmesh.types.BMFace`
210    * - Import/Create
211      - Poor *(inflexible)*
212      - Good *(supported as upgrade path)*
213      - Best
214    * - Manipulate
215      - Poor *(inflexible)*
216      - Poor *(loses ngons)*
217      - Best
218    * - Export/Output
219      - Good *(ngon support)*
220      - Good *(When ngons can't be used)*
221      - Good *(ngons, extra memory overhead)*
222
223 .. note::
224
225    Using the :mod:`bmesh` API is completely separate API from :mod:`bpy`,
226    typically you would would use one or the other based on the level of editing needed,
227    not simply for a different way to access faces.
228
229
230 Creating
231 --------
232
233 All 3 datatypes can be used for face creation.
234
235 - polygons are the most efficient way to create faces but the data structure is _very_ rigid and inflexible,
236   you must have all your vertices and faces ready and create them all at once.
237   This is further complicated by the fact that each polygon does not store its own verts,
238   rather they reference an index and size in :class:`bpy.types.Mesh.loops` which are a fixed array too.
239 - bmesh-faces are most likely the easiest way for new scripts to create faces,
240   since faces can be added one by one and the api has features intended for mesh manipulation.
241   While :class:`bmesh.types.BMesh` uses more memory it can be managed by only operating on one mesh at a time.
242
243
244 Editing
245 -------
246
247 Editing is where the 3 data types vary most.
248
249 - Polygons are very limited for editing,
250   changing materials and options like smooth works but for anything else
251   they are too inflexible and are only intended for storage.
252 - Tessfaces should not be used for editing geometry because doing so will cause existing ngons to be tessellated.
253 - BMesh-Faces are by far the best way to manipulate geometry.
254
255
256 Exporting
257 ---------
258
259 All 3 data types can be used for exporting,
260 the choice mostly depends on whether the target format supports ngons or not.
261
262 - Polygons are the most direct & efficient way to export providing they convert into the output format easily enough.
263 - Tessfaces work well for exporting to formats which don't support ngons,
264   in fact this is the only place where their use is encouraged.
265 - BMesh-Faces can work for exporting too but may not be necessary if polygons can be used
266   since using bmesh gives some overhead because its not the native storage format in object mode.
267
268
269 EditBones, PoseBones, Bone... Bones
270 ===================================
271
272 Armature Bones in Blender have three distinct data structures that contain them.
273 If you are accessing the bones through one of them, you may not have access to the properties you really need.
274
275 .. note::
276
277    In the following examples ``bpy.context.object`` is assumed to be an armature object.
278
279
280 Edit Bones
281 ----------
282
283 ``bpy.context.object.data.edit_bones`` contains a editbones;
284 to access them you must set the armature mode to edit mode first (editbones do not exist in object or pose mode).
285 Use these to create new bones, set their head/tail or roll, change their parenting relationships to other bones, etc.
286
287 Example using :class:`bpy.types.EditBone` in armature editmode:
288
289 This is only possible in edit mode.
290
291    >>> bpy.context.object.data.edit_bones["Bone"].head = Vector((1.0, 2.0, 3.0))
292
293 This will be empty outside of editmode.
294
295    >>> mybones = bpy.context.selected_editable_bones
296
297 Returns an editbone only in edit mode.
298
299    >>> bpy.context.active_bone
300
301
302 Bones (Object Mode)
303 -------------------
304
305 ``bpy.context.object.data.bones`` contains bones.
306 These *live* in object mode, and have various properties you can change,
307 note that the head and tail properties are read-only.
308
309 Example using :class:`bpy.types.Bone` in object or pose mode:
310
311 Returns a bone (not an editbone) outside of edit mode
312
313    >>> bpy.context.active_bone
314
315 This works, as with blender the setting can be edited in any mode
316
317    >>> bpy.context.object.data.bones["Bone"].use_deform = True
318
319 Accessible but read-only
320
321    >>> tail = myobj.data.bones["Bone"].tail
322
323
324 Pose Bones
325 ----------
326
327 ``bpy.context.object.pose.bones`` contains pose bones.
328 This is where animation data resides, i.e. animatable transformations
329 are applied to pose bones, as are constraints and ik-settings.
330
331 Examples using :class:`bpy.types.PoseBone` in object or pose mode:
332
333 .. code-block:: python
334
335    # Gets the name of the first constraint (if it exists)
336    bpy.context.object.pose.bones["Bone"].constraints[0].name
337
338    # Gets the last selected pose bone (pose mode only)
339    bpy.context.active_pose_bone
340
341
342 .. note::
343
344    Notice the pose is accessed from the object rather than the object data,
345    this is why blender can have 2 or more objects sharing the same armature in different poses.
346
347 .. note::
348
349    Strictly speaking PoseBone's are not bones, they are just the state of the armature,
350    stored in the :class:`bpy.types.Object` rather than the :class:`bpy.types.Armature`,
351    the real bones are however accessible from the pose bones - :class:`bpy.types.PoseBone.bone`
352
353
354 Armature Mode Switching
355 -----------------------
356
357 While writing scripts that deal with armatures you may find you have to switch between modes,
358 when doing so take care when switching out of edit-mode not to keep references
359 to the edit-bones or their head/tail vectors.
360 Further access to these will crash blender so its important the script
361 clearly separates sections of the code which operate in different modes.
362
363 This is mainly an issue with editmode since pose data can be manipulated without having to be in pose mode,
364 however for operator access you may still need to enter pose mode.
365
366
367 Data Names
368 ==========
369
370
371 Naming Limitations
372 ------------------
373
374 A common mistake is to assume newly created data is given the requested name.
375
376 This can cause bugs when you add some data (normally imported) then reference it later by name.
377
378 .. code-block:: python
379
380    bpy.data.meshes.new(name=meshid)
381
382    # normally some code, function calls...
383    bpy.data.meshes[meshid]
384
385
386 Or with name assignment...
387
388 .. code-block:: python
389
390    obj.name = objname
391
392    # normally some code, function calls...
393    obj = bpy.data.meshes[objname]
394
395
396 Data names may not match the assigned values if they exceed the maximum length, are already used or an empty string.
397
398
399 Its better practice not to reference objects by names at all,
400 once created you can store the data in a list, dictionary, on a class etc,
401 there is rarely a reason to have to keep searching for the same data by name.
402
403 If you do need to use name references, its best to use a dictionary to maintain
404 a mapping between the names of the imported assets and the newly created data,
405 this way you don't run this risk of referencing existing data from the blend file, or worse modifying it.
406
407 .. code-block:: python
408
409    # typically declared in the main body of the function.
410    mesh_name_mapping = {}
411
412    mesh = bpy.data.meshes.new(name=meshid)
413    mesh_name_mapping[meshid] = mesh
414
415    # normally some code, or function calls...
416
417    # use own dictionary rather than bpy.data
418    mesh = mesh_name_mapping[meshid]
419
420
421 Library Collisions
422 ------------------
423
424 Blender keeps data names unique - :class:`bpy.types.ID.name` so you can't name two objects,
425 meshes, scenes etc the same thing by accident.
426
427 However when linking in library data from another blend file naming collisions can occur,
428 so its best to avoid referencing data by name at all.
429
430 This can be tricky at times and not even blender handles this correctly in some case
431 (when selecting the modifier object for eg you can't select between multiple objects with the same name),
432 but its still good to try avoid problems in this area.
433
434
435 If you need to select between local and library data, there is a feature in ``bpy.data`` members to allow for this.
436
437 .. code-block:: python
438
439    # typical name lookup, could be local or library.
440    obj = bpy.data.objects["my_obj"]
441
442    # library object name look up using a pair
443    # where the second argument is the library path matching bpy.types.Library.filepath
444    obj = bpy.data.objects["my_obj", "//my_lib.blend"]
445
446    # local object name look up using a pair
447    # where the second argument excludes library data from being returned.
448    obj = bpy.data.objects["my_obj", None]
449
450    # both the examples above also works for 'get'
451    obj = bpy.data.objects.get(("my_obj", None))
452
453
454 Relative File Paths
455 ===================
456
457 Blenders relative file paths are not compatible with standard Python modules such as ``sys`` and ``os``.
458
459 Built in Python functions don't understand blenders ``//`` prefix which denotes the blend file path.
460
461 A common case where you would run into this problem is when exporting a material with associated image paths.
462
463    >>> bpy.path.abspath(image.filepath)
464
465
466 When using blender data from linked libraries there is an unfortunate complication
467 since the path will be relative to the library rather than the open blend file.
468 When the data block may be from an external blend file pass the library argument from the :class:`bpy.types.ID`.
469
470    >>> bpy.path.abspath(image.filepath, library=image.library)
471
472
473 These returns the absolute path which can be used with native Python modules.
474
475
476 Unicode Problems
477 ================
478
479 Python supports many different encodings so there is nothing stopping you from
480 writing a script in ``latin1`` or ``iso-8859-15``.
481
482 See `pep-0263 <https://www.python.org/dev/peps/pep-0263/>`_
483
484 However this complicates matters for Blender's Python API because ``.blend`` files don't have an explicit encoding.
485
486 To avoid the problem for Python integration and script authors we have decided all strings in blend files
487 **must** be ``UTF-8``, ``ASCII`` compatible.
488
489 This means assigning strings with different encodings to an object names for instance will raise an error.
490
491 Paths are an exception to this rule since we cannot ignore the existence of non ``UTF-8`` paths on users file-system.
492
493 This means seemingly harmless expressions can raise errors, eg.
494
495    >>> print(bpy.data.filepath)
496    UnicodeEncodeError: 'ascii' codec can't encode characters in position 10-21: ordinal not in range(128)
497
498    >>> bpy.context.object.name = bpy.data.filepath
499    Traceback (most recent call last):
500      File "<blender_console>", line 1, in <module>
501    TypeError: bpy_struct: item.attr= val: Object.name expected a string type, not str
502
503
504 Here are 2 ways around filesystem encoding issues:
505
506    >>> print(repr(bpy.data.filepath))
507
508    >>> import os
509    >>> filepath_bytes = os.fsencode(bpy.data.filepath)
510    >>> filepath_utf8 = filepath_bytes.decode('utf-8', "replace")
511    >>> bpy.context.object.name = filepath_utf8
512
513
514 Unicode encoding/decoding is a big topic with comprehensive Python documentation,
515 to avoid getting stuck too deep in encoding problems - here are some suggestions:
516
517 - Always use utf-8 encoding or convert to utf-8 where the input is unknown.
518 - Avoid manipulating filepaths as strings directly, use ``os.path`` functions instead.
519 - Use ``os.fsencode()`` / ``os.fsdecode()`` instead of built in string decoding functions when operating on paths.
520 - To print paths or to include them in the user interface use ``repr(path)`` first
521   or ``"%r" % path`` with string formatting.
522
523 .. note::
524
525    Sometimes it's preferable to avoid string encoding issues by using bytes instead of Python strings,
526    when reading some input its less trouble to read it as binary data
527    though you will still need to decide how to treat any strings you want to use with Blender,
528    some importers do this.
529
530
531 Strange errors using 'threading' module
532 =======================================
533
534 Python threading with Blender only works properly when the threads finish up before the script does.
535 By using ``threading.join()`` for example.
536
537 Here is an example of threading supported by Blender:
538
539 .. code-block:: python
540
541    import threading
542    import time
543
544    def prod():
545        print(threading.current_thread().name, "Starting")
546
547        # do something vaguely useful
548        import bpy
549        from mathutils import Vector
550        from random import random
551
552        prod_vec = Vector((random() - 0.5, random() - 0.5, random() - 0.5))
553        print("Prodding", prod_vec)
554        bpy.data.objects["Cube"].location += prod_vec
555        time.sleep(random() + 1.0)
556        # finish
557
558        print(threading.current_thread().name, "Exiting")
559
560    threads = [threading.Thread(name="Prod %d" % i, target=prod) for i in range(10)]
561
562
563    print("Starting threads...")
564
565    for t in threads:
566        t.start()
567
568    print("Waiting for threads to finish...")
569
570    for t in threads:
571        t.join()
572
573
574 This an example of a timer which runs many times a second and moves
575 the default cube continuously while Blender runs **(Unsupported)**.
576
577 .. code-block:: python
578
579    def func():
580        print("Running...")
581        import bpy
582        bpy.data.objects['Cube'].location.x += 0.05
583
584    def my_timer():
585        from threading import Timer
586        t = Timer(0.1, my_timer)
587        t.start()
588        func()
589
590    my_timer()
591
592 Use cases like the one above which leave the thread running once the script finishes
593 may seem to work for a while but end up causing random crashes or errors in Blender's own drawing code.
594
595 So far, no work has gone into making Blender's Python integration thread safe,
596 so until its properly supported, best not make use of this.
597
598 .. note::
599
600    Pythons threads only allow co-currency and won't speed up your scripts on multi-processor systems,
601    the ``subprocess`` and ``multiprocess`` modules can be used with Blender and make use of multiple CPU's too.
602
603
604 Help! My script crashes Blender
605 ===============================
606
607 **TL;DR:** Do not keep direct references to Blender data (of any kind) when modifying the container
608 of that data, and/or when some undo/redo may happen (e.g. during modal operators execution...).
609 Instead, use indices (or other data always stored by value in Python, like string keys...),
610 that allow you to get access to the desired data.
611
612 Ideally it would be impossible to crash Blender from Python
613 however there are some problems with the API where it can be made to crash.
614
615 Strictly speaking this is a bug in the API but fixing it would mean adding memory verification
616 on every access since most crashes are caused by the Python objects referencing Blenders memory directly,
617 whenever the memory is freed or re-allocated, further Python access to it can crash the script.
618 But fixing this would make the scripts run very slow,
619 or writing a very different kind of API which doesn't reference the memory directly.
620
621 Here are some general hints to avoid running into these problems.
622
623 - Be aware of memory limits,
624   especially when working with large lists since Blender can crash simply by running out of memory.
625 - Many hard to fix crashes end up being because of referencing freed data,
626   when removing data be sure not to hold any references to it.
627 - Re-allocation can lead to the same issues
628   (e.g. if you add a lot of items to some Collection,
629   this can lead to re-allocating the underlying container's memory,
630   invalidating all previous references to existing items).
631 - Modules or classes that remain active while Blender is used,
632   should not hold references to data the user may remove, instead,
633   fetch data from the context each time the script is activated.
634 - Crashes may not happen every time, they may happen more on some configurations/operating-systems.
635 - Be wary of recursive patterns, those are very efficient at hiding the issues described here.
636 - See last sub-section about `Unfortunate Corner Cases`_ for some known breaking exceptions.
637
638 .. note::
639
640    To find the line of your script that crashes you can use the ``faulthandler`` module.
641    See the `faulthandler docs <https://docs.python.org/dev/library/faulthandler.html>`_.
642
643    While the crash may be in Blenders C/C++ code,
644    this can help a lot to track down the area of the script that causes the crash.
645
646 .. note::
647
648    Some container modifications are actually safe, because they will never re-allocate existing data
649    (e.g. linked lists containers will never re-allocate existing items when adding or removing others).
650
651    But knowing which cases are safe and which aren't implies a deep understanding of Blender's internals.
652    That's why, unless you are willing to dive into the RNA C implementation, it's simpler to
653    always assume that data references will become invalid when modifying their containers,
654    in any possible way.
655
656
657 **Don’t:**
658
659 .. code-block:: python
660
661    class TestItems(bpy.types.PropertyGroup):
662        name: bpy.props.StringProperty()
663
664    bpy.utils.register_class(TestItems)
665    bpy.types.Scene.test_items = bpy.props.CollectionProperty(type=TestItems)
666
667    first_item = bpy.context.scene.test_items.add()
668    for i in range(100):
669        bpy.context.scene.test_items.add()
670
671    # This is likely to crash, as internal code may re-allocate
672    # the whole container (the collection) memory at some point.
673    first_item.name = "foobar"
674
675
676 **Do:**
677
678 .. code-block:: python
679
680    class TestItems(bpy.types.PropertyGroup):
681        name: bpy.props.StringProperty()
682
683    bpy.utils.register_class(TestItems)
684    bpy.types.Scene.test_items = bpy.props.CollectionProperty(type=TestItems)
685
686    first_item = bpy.context.scene.test_items.add()
687    for i in range(100):
688        bpy.context.scene.test_items.add()
689
690    # This is safe, we are getting again desired data *after*
691    # all modifications to its container are done.
692    first_item = bpy.context.scene.test_items[0]
693    first_item.name = "foobar"
694
695
696 Undo/Redo
697 ---------
698
699 Undo invalidates all :class:`bpy.types.ID` instances (Object, Scene, Mesh, Lamp... etc).
700
701 This example shows how you can tell undo changes the memory locations.
702
703    >>> hash(bpy.context.object)
704    -9223372036849950810
705    >>> hash(bpy.context.object)
706    -9223372036849950810
707
708    # ... move the active object, then undo
709
710    >>> hash(bpy.context.object)
711    -9223372036849951740
712
713 As suggested above, simply not holding references to data when Blender is used
714 interactively by the user is the only way to ensure the script doesn't become unstable.
715
716
717 Undo & Library Data
718 ^^^^^^^^^^^^^^^^^^^
719
720 One of the advantages with Blenders library linking system that undo
721 can skip checking changes in library data since it is assumed to be static.
722
723 Tools in Blender are not allowed to modify library data.
724
725 Python however does not enforce this restriction.
726
727 This can be useful in some cases, using a script to adjust material values for example.
728 But its also possible to use a script to make library data point to newly created local data,
729 which is not supported since a call to undo will remove the local data
730 but leave the library referencing it and likely crash.
731
732 So it's best to consider modifying library data an advanced usage of the API
733 and only to use it when you know what you're doing.
734
735
736 Edit Mode / Memory Access
737 -------------------------
738
739 Switching edit-mode ``bpy.ops.object.mode_set(mode='EDIT')`` / ``bpy.ops.object.mode_set(mode='OBJECT')``
740 will re-allocate objects data,
741 any references to a meshes vertices/polygons/uvs, armatures bones,
742 curves points etc cannot be accessed after switching edit-mode.
743
744 Only the reference to the data its self can be re-accessed, the following example will crash.
745
746 .. code-block:: python
747
748    mesh = bpy.context.active_object.data
749    polygons = mesh.polygons
750    bpy.ops.object.mode_set(mode='EDIT')
751    bpy.ops.object.mode_set(mode='OBJECT')
752
753    # this will crash
754    print(polygons)
755
756
757 So after switching edit-mode you need to re-access any object data variables,
758 the following example shows how to avoid the crash above.
759
760 .. code-block:: python
761
762    mesh = bpy.context.active_object.data
763    polygons = mesh.polygons
764    bpy.ops.object.mode_set(mode='EDIT')
765    bpy.ops.object.mode_set(mode='OBJECT')
766
767    # polygons have been re-allocated
768    polygons = mesh.polygons
769    print(polygons)
770
771
772 These kinds of problems can happen for any functions which re-allocate
773 the object data but are most common when switching edit-mode.
774
775
776 Array Re-Allocation
777 -------------------
778
779 When adding new points to a curve or vertices/edges/polygons to a mesh,
780 internally the array which stores this data is re-allocated.
781
782 .. code-block:: python
783
784    bpy.ops.curve.primitive_bezier_curve_add()
785    point = bpy.context.object.data.splines[0].bezier_points[0]
786    bpy.context.object.data.splines[0].bezier_points.add()
787
788    # this will crash!
789    point.co = 1.0, 2.0, 3.0
790
791 This can be avoided by re-assigning the point variables after adding the new one or by storing
792 indices to the points rather than the points themselves.
793
794 The best way is to sidestep the problem altogether add all the points to the curve at once.
795 This means you don't have to worry about array re-allocation and its faster too
796 since reallocating the entire array for every point added is inefficient.
797
798
799 Removing Data
800 -------------
801
802 **Any** data that you remove shouldn't be modified or accessed afterwards,
803 this includes f-curves, drivers, render layers, timeline markers, modifiers, constraints
804 along with objects, scenes, collections, bones.. etc.
805
806 The ``remove()`` api calls will invalidate the data they free to prevent common mistakes.
807
808 The following example shows how this precaution works.
809
810 .. code-block:: python
811
812    mesh = bpy.data.meshes.new(name="MyMesh")
813    # normally the script would use the mesh here...
814    bpy.data.meshes.remove(mesh)
815    print(mesh.name)  # <- give an exception rather than crashing:
816
817    # ReferenceError: StructRNA of type Mesh has been removed
818
819
820 But take care because this is limited to scripts accessing the variable which is removed,
821 the next example will still crash.
822
823 .. code-block:: python
824
825    mesh = bpy.data.meshes.new(name="MyMesh")
826    vertices = mesh.vertices
827    bpy.data.meshes.remove(mesh)
828    print(vertices)  # <- this may crash
829
830
831 Unfortunate Corner Cases
832 ------------------------
833
834 Besides all expected cases listed above, there are a few others that should not be
835 an issue but, due to internal implementation details, currently are:
836
837 - ``Object.hide_viewport``, ``Object.hide_select`` and ``Object.hide_render``:
838   Setting any of those booleans will trigger a rebuild of Collection caches, hence breaking
839   any current iteration over ``Collection.all_objects``.
840
841
842 sys.exit
843 ========
844
845 Some Python modules will call ``sys.exit()`` themselves when an error occurs,
846 while not common behavior this is something to watch out for because it may seem
847 as if Blender is crashing since ``sys.exit()`` will close Blender immediately.
848
849 For example, the ``argparse`` module will print an error and exit if the arguments are invalid.
850
851 An ugly way of troubleshooting this is to set ``sys.exit = None`` and see what line of Python code is quitting,
852 you could of course replace ``sys.exit`` with your own function but manipulating Python in this way is bad practice.