From 260b75a952f40961d3e06c9a7f48ec9b696bf169 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 14 Sep 2022 15:11:50 +1000 Subject: [PATCH] PyDoc: add an "Advanced" section to document WITH_PYTHON_MODULE Document the use cases, usage and limitations of using Blender as a Python module. --- doc/python_api/rst/info_advanced.rst | 15 +++ .../rst/info_advanced_blender_as_bpy.rst | 124 ++++++++++++++++++ doc/python_api/sphinx_doc_gen.py | 11 +- 3 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 doc/python_api/rst/info_advanced.rst create mode 100644 doc/python_api/rst/info_advanced_blender_as_bpy.rst diff --git a/doc/python_api/rst/info_advanced.rst b/doc/python_api/rst/info_advanced.rst new file mode 100644 index 00000000000..cae1e711722 --- /dev/null +++ b/doc/python_api/rst/info_advanced.rst @@ -0,0 +1,15 @@ +.. _info_advanced-index: + +******** +Advanced +******** + +This chapter covers advanced use (topics which may not be required for typical usage). + +.. NOTE(@campbellbarton): Blender-as-a-Python-module is too obscure a topic to list directly on the main-page, + so opt for an "Advanced" page which can be expanded on as needed. + +.. toctree:: + :maxdepth: 1 + + info_advanced_blender_as_bpy.rst diff --git a/doc/python_api/rst/info_advanced_blender_as_bpy.rst b/doc/python_api/rst/info_advanced_blender_as_bpy.rst new file mode 100644 index 00000000000..b3fbfd2fe6d --- /dev/null +++ b/doc/python_api/rst/info_advanced_blender_as_bpy.rst @@ -0,0 +1,124 @@ + +************************** +Blender as a Python Module +************************** + +Blender supports being built as a Python module, +allowing ``import bpy`` to be added to any Python script, providing access to Blender's features. + +.. note:: + + At time of writing official builds are not available, + using this requires compiling Blender yourself see + `build instructions `__. + + +Use Cases +========= + +Python developers may wish to integrate Blender scripts which don't center around Blender. + +Possible uses include: + +- Visualizing data by rendering images and animations. +- Image processing using Blender's compositor. +- Video editing (using Blender's sequencer). +- 3D file conversion. +- Development, accessing ``bpy`` from Python IDE's and debugging tools for example. +- Automation. + + +Usage +===== + +For the most part using Blender as a Python module is equivalent to running a script in background-mode +(passing the command-line arguments ``--background`` or ``-b``), +however there are some differences to be aware of. + +.. Sorted alphabetically as there isn't an especially a logical order to show them. + +Blender's Executable Access + The attribute :class:`bpy.app.binary_path` defaults to an empty string. + + If you wish to point this to the location of a known executable you may set the value. + + This example searches for the binary, setting it when found: + + .. code-block:: python + + import bpy + import shutil + + blender_bin = shutil.which("blender") + if blender_bin: + print("Found:", blender_bin) + bpy.app.binary_path = blender_bin + else: + print("Unable to find blender!") + +Blender's Internal Modules + There are many modules included with Blender such as :mod:`gpu` and :mod:`mathuils`. + It's important that these are imported after ``bpy`` or they will not be found. + +Command Line Arguments Unsupported + Functionality controlled by command line arguments (shown by calling ``blender --help`` aren't accessible). + + Typically this isn't such a limitation although there are some command line arguments that don't have + equivalents in Blender's Python API (``--threads`` and ``--log`` for example). + + .. note:: + + Access to these settings may be added in the future as needed. + +Resource Sharing (GPU) + It's possible other Python modules make use of the GPU in a way that prevents Blender/Cycles from accessing the GPU. + +Signal Handlers + Blender's typical signal handlers are not initialized, so there is no special handling for ``Control-C`` + to cancel a render and a crash log is not written in the event of a crash. + +Startup and Preferences + When the ``bpy`` module loads, the file is not empty as you might expect, + there is a default cube, camera and light. If you wish to start from a blank file use: + ``bpy.ops.wm.read_factory_settings(use_empty=True)``. + + The users startup and preferences are ignored to prevent your local configuration from impacting scripts behavior. + The Python module behaves as if ``--factory-startup`` was passed as a command line argument. + + The users preferences and startup can be loaded using operators: + + .. code-block:: python + + import bpy + + bpy.ops.wm.read_userpref() + bpy.ops.wm.read_homefile() + + +Limitations +=========== + +Most constraints of Blender as an application still apply: + +Reloading Unsupported + Reloading via ``importlib.reload`` will raise an exception instead of reloading and resetting the module. + + The operator ``bpy.ops.wm.read_factory_settings()`` can be used to reset the internal state. + +Single Blend File Restriction + Only a single ``.blend`` file can be edited at a time. + + .. hint:: + + As with the application it's possible to start multiple instances, + each with their own ``bpy`` and therefor Blender state. + Python provides the ``multiprocessing`` module to make communicating with sub-processes more convenient. + + In some cases the library API may be an alternative to starting separate processes, + although this API operates on reading and writing ID data-blocks and isn't + a complete substitute for loading ``.blend`` files, see: + + - :meth:`bpy.types.BlendDataLibraries.load` + - :meth:`bpy.types.BlendDataLibraries.write` + - :meth:`bpy.types.BlendData.temp_data` + supports a temporary data-context to avoid manipulating the current ``.blend`` file. diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 240bec6fd30..e07afe44545 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -402,8 +402,15 @@ INFO_DOCS = ( "Tips and Tricks: Hints to help you while writing scripts for Blender"), ("info_gotcha.rst", "Gotcha's: Some of the problems you may encounter when writing scripts"), + ("info_advanced.rst", + "Advanced use (topics which may not be required for typical usage)"), ("change_log.rst", "Change Log: List of changes since last Blender release"), ) +# Referenced indirectly. +INFO_DOCS_OTHER = ( + # Included by: `info_advanced.rst`. + "info_advanced_blender_as_bpy.rst", +) # only support for properties atm. RNA_BLACKLIST = { @@ -1470,7 +1477,7 @@ def pyrna2sphinx(basepath): struct_module_name = struct.module_name if USE_ONLY_BUILTIN_RNA_TYPES: - assert(struct_module_name == "bpy.types") + assert (struct_module_name == "bpy.types") filepath = os.path.join(basepath, "%s.%s.rst" % (struct_module_name, struct.identifier)) file = open(filepath, "w", encoding="utf-8") fw = file.write @@ -2314,6 +2321,8 @@ def copy_handwritten_rsts(basepath): if not EXCLUDE_INFO_DOCS: for info, _info_desc in INFO_DOCS: shutil.copy2(os.path.join(RST_DIR, info), basepath) + for info in INFO_DOCS_OTHER: + shutil.copy2(os.path.join(RST_DIR, info), basepath) # TODO: put this docs in Blender's code and use import as per modules above. handwritten_modules = [