Skip to content
This repository has been archived by the owner on May 9, 2024. It is now read-only.

Latest commit

 

History

History

install_dependencies

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

Install dependencies

Note

Blender 4.2 will introduce the Blender Extension Platform. Extensions allow to properly manage dependencies through a manifest. The approach shown in this repository is only a workaround for Blender versions before 4.2 and should no longer be used in the future.

For more details see:

Description

This add-on demonstrates how to install Python packages from within Blender. Elevated privileges may be required, depending on the permissions set on Blender's directory.

Implementation

Dependencies

The required dependencies are declared at the beginning the form a tuple of namedtuple and the installation state of the dependencies is stored as boolean in dependencies_installed. Please note that this should only contain the dependencies that will need to be installed through pip. Other parts of your add-on can and should be imported as usual through a simple import statement instead of a dynamic import.

Registration

The registration is split into three steps:

  1. Register the classes related to the add-on's preferences and a panel with installation instructions.
  2. Check if the required dependencies are installed and try to import them. Only proceed to 3.) if the modules can be found and set dependencies_installed to true.
  3. Register all other classes, e.g. panels, operators, etc.

The user will see a panel with installation instructions (EXAMPLE_PT_warning_panel) in place of the actual operators should step 2.) fail. In case it is successful, EXAMPLE_PT_warning_panel won't be displayed. This is because the poll method checks dependencies_installed.

image

Add-on's preferences

The add-on's preferences are implemented by EXAMPLE_preferences, which display the operator EXAMPLE_OT_install_dependencies. This creates a button in the details section of the add-on's preferences that allows the user to install the required Python packages. It calls the install_pip function to install pip and install_and_import_module() function to install and import the dependencies. If this step is successful the dependencies_installed is set to true and the remaining panels, operators, etc. are registered as well.

image

The design that requires the user to manually press a button in the preferences, instead of automatically installing the packages, is intentional. The user should give explicit consent when files are downloaded from the internet and Python packages are installed on their system. The Blender Foundation takes their user's privacy and security serious, as an add-on developer you should as well.

Preparing pip

The installation of packages requires pip. Only the Windows release of Blender includes pip, therefore it is necessary to install it through ensurepip.bootstrap() for all other operating systems which is done in install_pip. ensurepip.bootstrap() calls pip. During its execution pip sets the environment variable PIP_REQ_TRACKER which is used as a temporary directory. Unfortunately pip doesn't remove the environment variable and subsequent calls to pip will attempt to use the path in PIP_REQ_TRACKER as temporary directory. However, this directory doesn't exist anymore and the pip would throw an exception. Therefore, os.environ.pop("PIP_REQ_TRACKER", None) is needed.

Installing the package

Blender excludes the user site-packages from its sys.path by default and is therefore not able to import these packages. This is done to prevent the accidental loading of packages installed by the system's Python which may be incompatible to Blender's Python version. However, by default pip would still check the user site-packages when it tries to determine if the requirements are already satisfied. That would be incorrect for Blender, since it needs them to be installed for its own Python interpreter. Therefore, PYTHONNOUSERSITE is temporarily set to prevent pip from checking the user site-packages when trying to determine if the packages are already installed. The package installation is accomplished by calling pip through subprocess. The path to the Python binary is given by sys.executable. If you need to support Blender versions prior to 2.91.0, then you have to check bpy.app.version and use bpy.app.binary_path_python in older versions of Blender. Once the installation has been attempted, the PYTHONNOUSERSITE environment variable is removed.

Importing the module

The programmatic import is done through importlib.import_module() and the result is assigned to the global symbol table dictionary returned by globals().

The user's perspective

The user installs the add-on through the user preferences (Edit > Preferences > Add-ons). They might check the sidebar where they expect to find the add-on's operators, but find the panel with the installation instructions instead. Hence they go back to the preferences, open the details section of the add-on and press the button to install the dependencies. Once the install is completed the tab in the sidebar shows all operators as expected.

Failures during installation are reported to the user in a popup. In case the add-on is executed as a script, instead of being installed as add-on, it will display the installation instructions in the sidebar as well.

Improvement suggestions for your own add-on

  • Show a more descriptive error message when a "permission denied" error occurs during the installation of packages. Inform the user that elevated permission are necessary and provide instructions to resolve the issue. Ideally Blender shouldn't be started with elevated permissions, since this would be against security best practice. Therefore, you could provide instructions to install the packages manually and include a requirements.txt.

Additional Information

The add-on was originally developed as an answer to the this question on Blender's StackExchange.

Change log

1.0.4 - 2020-11-30

Compatible Blender versions: 2.91

Commit hash: c7ba15da33da9e83d83f8750a2fa0f22c1cc81b2

Changes:

  • Replace the deprecated bpy.app.binary_path_python with sys.executable. For compatibility with version prior to 2.91.0 you would have to modify the code. Check bpy.app.version and select the appropriate way to get the path to the Python interpreter for that Blender version.
  • Simplify handling of environment variables (see #3).
  • Check if the dependecy has a __version__ attribute, before attempting to display it in a label. This fix was suggested by @StefanKarlsson987.

1.0.3 - 2020-10-19

Compatible Blender versions: 2.81 to 2.90

Commit hash: 8bf7ddefb458e697d51ca5bd74185890146d4e9d

Changes:

  • Prevent pip from checking the user site-packages to determine if requirements are satisfied. Blender cannot import packages from user site-packages by default, as this has been intentionally disabled by commit rB79a58eef059ffc3f12d11bd68938cfb1b4cd2462.

1.0.2 - 2020-05-20

Compatible Blender versions: 2.81 to 2.90

Commit hash: cd3597939d77e37bb45434533440d56262f01a55

Changes:

  • Fix install_pip for when the ensurepip module is not available but pip is already installed

1.0.1 - 2020-05-19

Compatible Blender versions: 2.81 to 2.90

Commit hash: 211e51a3ac2a83f4f1db5a80c59eded138acbf40

Changes:

  • Refactor install_and_import_module() and place installation of pip in a separate function install_pip

1.0.0 - 2020-05-18

Compatible Blender versions: 2.81 to 2.90

Commit hash: 226ef43cf003511b6220e7135d4b6a8289729582

Changes:

  • Initial version