1
$\begingroup$

I've been trying to get PIL to install via the DECALmachine addon. I've ensured that my Python on my Windows machine is up to date: Python 3.8, PIP upgraded, PIL installed. I know that Blender uses its own Python.exe. Is there a way to get Blender to use my machine's Python? I haven't been able to find where the PIL DLL is install to attempt to move it inside the Blender bin folder.

I've ensured that all my Blender Foundation (and below) allow not only my user account by Admin account have total access via the Properties. I've run Blender in Admin mode and clicked the Admin options to install PIL inside the Addon DECAL interface, nothing turns the checkmark to green.

The first error I get is:

Ensurepip: C:\Program Files\Blender Foundation\Blender 2.82\2.82\python\lib\ensurepip False

I've confirmed this module is installed properly.

Has anyone else dealt with this?

Thank you in advance.

$\endgroup$
  • $\begingroup$ blender.stackexchange.com/search?q=%5Bpython%5D+system+python If your blender and system python are same (x.y) to have 3rd party module available for both system and blender can pip3.8 install --user foo To use system python can rename python folder in installation. (See other answers in search link above, for other methods that may suit) $\endgroup$ – batFINGER Apr 10 at 9:10
2
$\begingroup$

Blender doesn't use your system's Python interpreter by default. That would require the use of --python-use-system-env in Blender 2.82 and later (see this answer for more information). Additionally your system's Python interpreter and modules would need to be compatible with the version Blender expects. Blender 2.82 use Python 3.7.4.

While it's unclear why DECALmachine fails to install Pillow, it shouldn't be necessary to use your system's Python interpreter. The script below will try to install the package and import the module.

  1. Start Blender and open the Scripting workspace
  2. Create a new text block (Text > New)
  3. Copy and paste the script into the text editor
  4. Open the console (Window > Toggle System Console)
  5. Run the script and check the output of the console for errors.

import bpy
import os
import ensurepip
import subprocess


try:
    import PIL
except ImportError:
    # The import failed, therefore we check that pip is available and attempt to install the package.

    # ensurepip.bootstrap() also calls pip, which adds the environment variable PIP_REQ_TRACKER. After 
    # ensurepip.bootstrap() finishes execution, the directory doesn't exist anymore. However, when subprocess 
    # is used to call pip, in order to install a package, the environment variables still contain 
    # PIP_REQ_TRACKER with the now nonexistent path. This is a problem since pip checks if PIP_REQ_TRACKER is 
    # set and if it is, attempts to use it as temp directory. This would result in an error because the 
    # directory couldn't be found. Therefore, PIP_REQ_TRACKER needs to be removed from os.environ.
    ensurepip.bootstrap()
    os.environ.pop("PIP_REQ_TRACKER", None)

    # Try to install the package. This may fail with subprocess.CalledProcessError
    subprocess.run([bpy.app.binary_path_python, "-m", "pip", "install", "Pillow"], check=True)
    import PIL


print(PIL.__version__)

A more generic version that allows install packages in a simple way:

import bpy


def ensure_and_import_module(module_name, package_name=None, global_name=None):
    """
    Ensures that the required package is installed and imports the module. It will attempt to install the package
    through pip if the import of the module fails.
    :param module_name: Module to import.
    :param package_name: (Optional) Name of the package that needs to be installed. If None it is assumed to be equal
       to the module_name.
    :param global_name: (Optional) Name under which the module is imported. If None the module_name will be used.
       This allows to import under a different name with the same effect as e.g. "import numpy as np" where "np" is
       the global_name under which the module can be accessed.
    :raises: subprocess.CalledProcessError and ImportError
    """
    import os
    import sys
    import importlib
    import ensurepip
    import subprocess

    if package_name is None:
        package_name = module_name

    if global_name is None:
        global_name = module_name

    try:
        # Attempt to import the module and assign it to globals dictionary. This allow to access the module under
        # the given name, just like the regular import would.
        globals()[global_name] = importlib.import_module(module_name)
    except ImportError:
        # The import failed, therefore we check that pip is available and attempt to install the package.

        # ensurepip.bootstrap() also calls pip, which adds the environment variable PIP_REQ_TRACKER. After 
        # ensurepip.bootstrap() finishes execution, the directory doesn't exist anymore. However, when subprocess 
        # is used to call pip, in order to install a package, the environment variables still contain 
        # PIP_REQ_TRACKER with the now nonexistent path. This is a problem since pip checks if PIP_REQ_TRACKER is 
        # set and if it is, attempts to use it as temp directory. This would result in an error because the 
        # directory couldn't be found. Therefore, PIP_REQ_TRACKER needs to be removed from os.environ.

        ensurepip.bootstrap()
        os.environ.pop("PIP_REQ_TRACKER", None)

        # Try to install the package. This may fail with subprocess.CalledProcessError
        subprocess.run([bpy.app.binary_path_python, "-m", "pip", "install", package_name], check=True)

        # The installation succeeded, attempt to import the module again
        globals()[global_name] = importlib.import_module(module_name)


# Make sure that Pillow is installed and PIL can be imported
ensure_and_import_module("PIL", "Pillow")
print(PIL.__version__)
| improve this answer | |
$\endgroup$
  • $\begingroup$ Thank you very much for the script. It failed on "import ensurepip" however from the terminal, it says that it's already installed when running from python.exe within the bin directory. $\endgroup$ – Dr Tyrell Apr 10 at 11:57
  • $\begingroup$ @DrTyrell What command are you running in the terminal to check this? Apparently you have broken something in your Blender/Blender's Python installation if ensurepip can't be imported. $\endgroup$ – Robert Gützkow Apr 10 at 11:59
  • $\begingroup$ Will it break everything if I'm running purely Python 3.8? $\endgroup$ – Dr Tyrell Apr 10 at 12:04
  • $\begingroup$ @DrTyrell I haven't tested it, but I would assume that there could be some incompatibilities. Since it would be a guessing game to figure out how/what exactly broke your install, please uninstall Blender 2.82 and delete C:\Users\[insert username here]\AppData\Roaming\Blender Foundation\Blender\2.82. This will completely remove all preferences/keymaps/add-ons. Install the most recent stable version of Blender. Don't mess with the file/directory permissions and use the Python interpreter that is included in Blender. $\endgroup$ – Robert Gützkow Apr 10 at 12:14
  • $\begingroup$ I switched back to 3.7.4 and ran everything from an Admin level account for install, and it worked. One does have to manually update pip and ensurepip, then run Blender from Admin permission, pressed the Install PIL Admin and it BING it worked. Then restarted Blender and we're good to go. Thank you again! $\endgroup$ – Dr Tyrell Apr 10 at 12:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.