Blender Python Scripting

Notes on using Blender to create the UI for a Python app.

Installing packages

Blender uses its own bundled Python interpreter. While some packages come with it by default (eg numpy), I needed to install more packages. I tried 3 options.

  1. Installing packages via pip on Blender Python
  • This can be done via a script, eg:
import subprocess
import sys
import os
 
# path to python.exe (DEPENDS ON OS!)
python_exe = os.path.join(sys.prefix, 'bin', 'python3.7m') # Mac
#python_exe = os.path.join(sys.prefix, 'bin', 'python.exe') # Windows, probably
 
# upgrade pip
subprocess.call([python_exe, "-m", "ensurepip"])
subprocess.call([python_exe, "-m", "pip", "install", "--upgrade", "pip"])
 
# install required packages
subprocess.call([python_exe, "-m", "conda", "install", "pygel3d"])
# ....
  • This could work out for all packages available via pip, however I do also need to use some packages that need to be built and installed from source (CGAL bindings, pygco). Not sure how those could be dealt with via a simple Python script.
  • This “pollutes” the default Python used by Blender on the user side, so not sure how good this would be to install on others' computer.
  • I didn’t pursue this to the end because I switched to solution (2).
  1. Simply/Lazily adding to the path the folder that contains all modules from my own base Conda environment
  • This is extremely simple to do locally, since that base Conda env already contains all necessary packages. It’s just 1 line at the beginning of the Python script:
sys.path.append('/Users/emilie/opt/anaconda3/lib/python3.7/site-packages')
  • But that caused terrible crashes, that seem to be caused by Intel MKL that is used by numpy. Looking up the problem I saw it could be caused by not correctly activating the conda environment. That’s why I tried solution 3.
  • Also that solution wouldn’t really work on any other machine than mine, where it would be necessary to install conda and all the packages.
  1. Creating a conda environment that replaces Blender default Python
  • First rename the default python folder to something else
cd /Applications/Blender.app/Contents/Resources/2.92
mv python _python
  • Create a conda environment in that folder, activate it and install all necessary packages. Make sure conda python version matches that of Blender (in 2.92 that is 3.7.7).
conda create --prefix ./python python=3.7.7
conda activate ./python
conda install numpy scipy matplotlib networkx
conda install -c conda-forge igl polyscope # scikit-learn
  • Problem: scikit-learn seems to be causing weird issues with Intel MKL used by numpy. Installing scikit-learn makes it impossible to use numpy from Blender scripts without a crash…
INTEL MKL ERROR: dlopen(/Applications/Blender-experiments.app/Contents/Resources/2.92/python/lib/libmkl_intel_thread.1.dylib, 9): Library not loaded: @rpath/libiomp5.dylib
  Referenced from: /Applications/Blender-experiments.app/Contents/Resources/2.92/python/lib/libmkl_intel_thread.1.dylib
  Reason: image not found.
Intel MKL FATAL ERROR: Cannot load libmkl_intel_thread.1.dylib.
Error: Not freed memory blocks: 57517, total unfreed memory 16.277855 MB
  • So we leave it out for now (luckily I wasn’t using it much, but this needs further investigation).
  • Then install modules that come through pip
pip install pygel3d potpourri3d PyMCubes meshio triangle
  • PyMCubes seems to be lacking a library, that I copied over manually, not sure why this used to work outside of Blender
cp /usr/lib/libc++.1.dylib /Applications/Blender.app/Contents/Resources/2.92/python/lib/python3.7/site-packages/mcubes
  • Then build and install manually the non-conda/non-pip stuff
# CGAL
# Clone CGAL-swig https://github.com/CGAL/cgal-swig-bindings
# CAUTION: in CMakeLists.txt, the Python version should be specified if there are multiple python version on the machine, otherwise things will fail
# eg: find_package(Python 3.7 EXACT COMPONENTS Interpreter Development)
# Build it following repo instructions (?) Not sure if that was necessary or if that was done by the install script anyway
# Install
python3 setup.py install

# pygco
# Clone https://github.com/yujiali/pygco (it should be my own fork, actually, once I've pushed that)
# Build it following repo instructions
# Import the scripts by calling: sys.path.append(PATH_TO_PYGCO_SCRIPTS)
  • At the end, do not forget to deactivate environment
conda deactivate
  • This workflow is pretty tedious but it works, and enables using Intel MKL (not sure whether that would be the case without conda).
  • Not sure whether that could be tractable to install on somebody else’s machine (let alone, windows machine). Look into docker container maybe?