Install script for Blender Addon Development in Eclipse

I constantly fiddle with a lot of Python scripts to automate or conduct experiments for my Geometry Processing endeavors using Blender. Usually, these scripts begin as a standalone and soon evolves as a fully functional addon. For the purpose of writing scripts in an efficient manner, I use Eclipse along with PyDev plugin. Once I have reached a certain stage of my addon development it becomes important to install and test the addon script often. In such a scenario the conventional route is to copy the addon folder with the python code to the Blender’s add-on directory. This proved to be a cumbersome process all the while and wasn’t a lot of fun, to begin with. But hey I use PyDev and Eclipse know well that a Python interpreter is available for it to use and run scripts from Eclipse.

The external tools configuration of Eclipse IDE. We can exploit this functionality to make our add-on development testing more easier.

In Eclipse IDE it is possible to create External tools configuration to run custom tasks and automate various process. With the python interpreter available it is possible to run a python script in the add-on directory that will copy itself to the Blender’s add-on folder to be installed as a plugin.

Firstly, we will look into the python script that can take care of installing (or copy) the add-on folder and its contents to the Blender add-on directory. Actually, the code is pretty much simple in its underlying logic. It reads the arguments supplied when running the script and then uses that information to install the plugin. The idea is to zip the contents of the folder and unzip it to the Blender’s add-on location.

import os, sys;
import subprocess;
from subprocess import Popen, PIPE;
import zipfile;
from platform import platform

BLENDER_ADDON_PREFIX = os.path.abspath(sys.argv[3].strip());
BLENDER_VERSION = sys.argv[4].strip();
BLENDER_ADDON_LOCATION = "%s/%s/scripts/addons/"%(BLENDER_ADDON_PREFIX,BLENDER_VERSION);
BLENDER_ADDON_LOCATION = os.path.abspath(BLENDER_ADDON_LOCATION);
PROJECT_FOLDER = os.path.abspath(sys.argv[1].strip());
PROJECT_NAME = sys.argv[2].strip();
EXTRAS_BLENDER_PATH = "";
try:
    EXTRAS_BLENDER_PATH = sys.argv[5];
except IndexError:
    pass;

print("Prefix: %s\nVERSION: %s\nADDON_LOCATION_FULL: %s\n"%(BLENDER_ADDON_PREFIX, BLENDER_VERSION, BLENDER_ADDON_LOCATION));

def zipdir(path, zipper):
    for root, dirs, files in os.walk(path):
        for file in files:
            if("." not in file[0] and not file.endswith('.zip') and "installaddon.py" not in file):
                file_path = os.path.abspath(os.path.join(root, file));
                parent_dir = os.path.abspath(os.path.join(os.getcwd(), os.pardir));
                rel_path = os.path.relpath(file_path, parent_dir);
                zipper.write(file_path, rel_path);
    
    return zipper;
    
if __name__ == "__main__":
    zipper = zipfile.ZipFile(PROJECT_NAME+".zip", 'w', zipfile.ZIP_DEFLATED);
    zipper = zipdir(PROJECT_FOLDER, zipper);
    zipper.close();
    zip_file_path = os.path.abspath(PROJECT_FOLDER+"/"+PROJECT_NAME+".zip");
    zipper = zipfile.ZipFile(zip_file_path, "r");
    
    zipper.extractall(BLENDER_ADDON_LOCATION);
    zipper.close();
    if(EXTRAS_BLENDER_PATH != ""):
        output = subprocess.Popen([EXTRAS_BLENDER_PATH], stdout=subprocess.PIPE).communicate()[0];
```   

Create a python script ‘installaddon.py’ and copy the above contents to this file. Now this file has to be available in the main folder where the __init__.py with all the bl_info values.

The typical folder structure of my Blender add-ons.

Now we have the needed script in place its time to configure Eclipse IDE to use this script. To do this you have to open the external tools configuration and create a new launch configuration.

Create a new launch configuration and supply the values as shown in the coming steps.

In the above screen shot the fields and their values are,

  • Name: The name of this tool and its entirely your choice
  • Location: The path to the executable to launch. This should point to the path of the Python interpreter binary. If you are on windows then this will point to the location of python.exe
  • Working Directory: It will be ${project_loc}. This will be an Eclipse variable pointing to the Eclipse project on which this tool is being executed.
  • Arguments: The arguments that need to be supplied to the executable, which in our case is the python interpreter.
    1. installaddon.py – Ask the python interpreter to run this script
    2. ${project_loc} – The first argument to the python script is the location of the project on the disk
    3. ${project_name} – The name of the project that will be the name of the Blender add-on as well
    4. ${string_prompt:Blender Addon Location:/path/to/blender/addon/location/before/version/folder}
    5. ${string_prompt:Version Text:2.79} – Which version of Blender are we targetting? Well, one can supply the full and final path to the Blender add-on location as the previous argument (argument 4). However, in my case, I test my addons with many versions of Blender. So this will help in that case
    6. ${string_prompt:Binary Text:blender} – The path to the Blender binary or executable. If supplied the addon will be installed and Blender will be called as a subprocess. It is a sheer matter of convenience. If left blank only the addon will be installed without invoking Blender.


Well, that’s it. I make it a point to copy this script to every Blender-addon project I have on Eclipse. Also by supply the arguments one can also run this script from the command line and achieve the same goal without using Eclipse. I have given the downloadables for everyone to use. Feel free to experiment and explore.

Hope this information is useful and be of some help to everyone out there. Goodluck and have a great life ahead.

Regards,

#0K

Blender + bundled python – Tricks

Use the code to find the artist, so the artist can create coders

On any operating system, I want to recommend download of standalone Blender instead of using the installer. The installer tries to copy the executable and necessary libraries at locations that need super privileges to make any changes. These situations can be avoided if you are running from a stand-alone Blender instance.

One hiccup when using a standalone Blender is that the bundled python usually lacks “setuptools” and “distutils for some standard package installations. While there are many ways to solve this problem

  1. On windows use Conda environment for Blender
  2. Ubuntu and Mac, install the python interpreter Blender needs
  3. or empower Blender’s bundled python

What I will discuss here is the 3rd option of empowering the Blender’s bundled python by adding distutils and setuptools. This way you don’t have to worry about downloading the huge anaconda setup for windows or go through a possible headache of compiling python from source for other systems. On Ubuntu you have the deadsnakes ppa but again this comes only with the dev packages and the interpreter itself. For the pip tools you have to manually do the get-pip.py step to install the required empowering tools. Rather this same idea of get-pip.py can be used to fix the bundled python of Blender.

First of all download the zipped or tarball of standalone Blender and unzip it to the location of your choice. Once you have downloaded and extracted it a location you should find the Blender folder with the much needed files and sub-folders inside it. Let us by an example to understand this better. If the choice is download version 2.79 then you shall find the embedded python at blenderlocation/2.79/python. Navigating to this directory will show you the below directories

Blender’s embedded python directory contents
  • bin – location that contains the embedded python interpreter
  • include – contains the include files for cythonic and other purposes
  • lib – the meaty part containing all the python packages

Fire up a terminal or command line utility and navigate to location blenderlocation/2.79/python/bin. Inside this folder you should see files as shown in the below screenshot,

The python interpreter shipped with the downloaded standalone Blender.

Run the command as shown in the below screenshot

Ensure you have curl installed and available. Then run curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py

Once you have finished getting the get-pip.py then proceed to executing the get-pip.py using the python executable inside the bin folder as shown in the below screenshot

Executing get-pip.py using the embedded python interpreter to install distutils and setuptools.

Step by step

- curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
- ./python3.5m get-pip.py

Once the get-pip.py has finished executing then the bin folder will be populated with executables of pip, easy_install etc.,

Executables related to distutils and setuptools. In third row, the first three entries are the executables of pip.

Now that we have installed the setuptools and distutils it is time to test its ability to install third-party packages. The below screenshot shows an example of installing scikit-learn using the pip tool we just arranged.

The pip installs the packages to the lib folder of the embedded python interpreter
The scikit-learn is now available for your downloaded standalone Blender

Shall we call it a day? or has the day just begun with the tools in place now?

Regards,

#0K

Python + Blender + import sklearn

Recently I upgraded my Ubuntu 16.04 to 18.04. I should admit it was a charm to update without any fuss or muss. However, there was one peculiar problem, it was about setting up the python plugins that I wrote/writing for my ongoing Ph.D. research projects. Everything was working fine until reinstalling Blender 2.79 and using the good old python plugins of my research.

My research is oriented towards geometry-processing and there is no other suitable candidate other than Blender, which caters to my itchy research needs. Blender supports a beautiful rendering system using cycles and can also allow one to write python code such that its prowess can be extended with only creativity as the limits. As said earlier my research is towards geometry-processing and demands a lot from linear algebra packages such as numpy, and scipy. Also, scikit-learn is an important package that I am dealing with lately. It was while trying to use scikit-learn I bumped into issues. The weird issue was when using the below statement from the Blender console,
from sklearn import preprocessing

Boom, I see another window with an error in the terminal, which says

from multiprocessing.semaphore_tracker import main;main(43)

After pulling out my hair over a few weeks I stumbled upon this link where this problem was being discussed. Following the read-up on this link lead me to this link. There the user mentions that the whole issue is a bug from multiprocessing python library.

The text from the last link states,

When SemaphoreTracker.ensure_running() from blender-2.79b-linux-glibc219-x86_64/2.79/python/lib/python3.5/multiprocessing/semaphore_tracker.py is executed it runs another Blender instance with arguments -c from multiprocessing.semaphore_tracker import main;main(9) by mistake.

It all became as clear as a day. A line (#55) in semaphore_tracker.py it tries to keep the python instance alive when importingsklearn. As we are running python as an instance inside the Blender software, the lineexe=spawn.get_executable() will return the path of the blender executable instead of the python interpreter inside Blender. Obviously, Blender is not a python instance. To fix this we have to manually point the variable to an actual python interpreter path used for Blender. This depends if you are using the system python or the bundled python. I would recommend that it is better to download and use the standalone Blender version instead of installable. Again the whole game behind this logic changes if you are a windows user. In this writing context, it is Ubuntu, so I chose to download the standalone version of Blender 2.79 and used the bundled python. So opening the file at /home/myusername/blender-2.79/2.79/python/lib/python3.5/multiprocessing/semaphore_tracker.py  and changing the line #55 in that python file to
exe = /home/myusername/blender-2.79/2.79/python/bin/python
solve the problem. As such I am not sure how good is this fix, however, it serves the purpose for now.

Regards,

#0K