Trying to install packages in Blender

It seems I continually run in to problems trying to use and install packages into blender. scipy did not work neither vistapy. Most of the docs for errors for these issues date back to 2.8 Now I am trying to get matplotlib to work but it returns the following:

Python: Traceback (most recent call last):
  File "U:\August 2022\Blender scripts .blend\Text.013", line 2, in <module>
  File "C:\Program Files\Blender Foundation\Blender 3.4\3.4\python\lib\site-packages\matplotlib\__init__.py", line 161, in <module>
    from . import _api, _version, cbook, _docstring, rcsetup
  File "C:\Program Files\Blender Foundation\Blender 3.4\3.4\python\lib\site-packages\matplotlib\cbook\__init__.py", line 30, in <module>
    from matplotlib import _api, _c_internal_utils
ImportError: cannot import name '_c_internal_utils' from partially initialized module 'matplotlib' (most likely due to a circular import) (C:\Program Files\Blender Foundation\Blender 3.4\3.4\python\lib\site-packages\matplotlib\__init__.py)

what’s the process you’re using for installing packages? some packages just don’t work in Blender due to how external dependencies resolve their paths. Pyside, for example won’t work because shiboken can’t be imported correctly. I haven’t tried matplotlib nor scipy so I can’t say if that’s the situation with these modules.

In situations where I need an external package that isn’t compatible with Blender for whatever reason, I just separate my logic into ‘blender’ and ‘external’ modules. To use it I just initialize the external script from the Blender script with os.system('python external_script.py') and then transfer data back and forth between the modules with SharedMemory buffers.

I found I could install the packages properly and working through CMD:

python -m pip install --no-deps packaging -t "C:\Program Files\Blender Foundation\Blender 3.4\3.4\python\lib\site-packages"

The problem being it continually starts to throw errors specific to stuff in the packages not being referenced properly

A couple of things:

  • have you tried running pip from the Blender python binary? using one version of python and pip to drop packages into another python’s environment could be problematic.

C:\Program Files\Blender Foundation\Blender 3.4\3.4\python\bin\Python.exe -m pip install etc etc

  • You’re using the --no-deps flag which explicitly tells pip to ignore dependencies. It stands to reason that if you’re installing a package and it needs dependencies that you’ve chosen to omit, you would run into problems with packages not existing or references being invalid.
1 Like

Usually I do this:

import sys
import subprocess

    
def ensure_import(package):
    try:
        import package
    except Exception as e:
        print('installing package', package)
        PYTHON_PATH = sys.executable
        subprocess.run([str(PYTHON_PATH), "-m", "pip", "install", package])

# example: make sure to show console first in order to get output
ensure_import('clipboard')
import clipboard
clipboard.copy("abc")  # now the clipboard content will be string "abc"
1 Like

Just in case someone stumbles upon this you can create a folder by your project and reuse your packages permanently for other projects as well using a sort of method like already stated, but maybe a bit more functional and avoiding continuous reinstalls:

import sys
import subprocess
import os
import bpy
import pkgutil

# Get the path to the Python interpreter used by Blender
python_path = sys.executable

# Determine the script directory
script_directory = os.path.dirname(bpy.data.filepath)

# Create a folder for packages
packages_directory = os.path.join(script_directory, "packages")
os.makedirs(packages_directory, exist_ok=True)

# Print the path
print("Blender's Python path:", python_path)

# Ensure pip is installed
subprocess.run([python_path, "-m", "ensurepip"])


# Check if the required packages are installed
required_packages = ["librosa", "pydub", "simpleaudio"]

installed_packages = {pkg.name for pkg in pkgutil.iter_modules()}

for package in required_packages:
    if package not in installed_packages:
        # Install the required package in the created folder
        subprocess.run([python_path, "-m", "pip", "install", "--target=" + packages_directory, package])
    else:
        print(f"{package} is already installed")

# Add the folder to the Python import path
sys.path.append(packages_directory)

# Import the installed packages

import numpy as np
import librosa
from pydub import AudioSegment
import simpleaudio as sa

# (Add the rest of your script here, including the custom nodes and operators)
def create_sine_wave(frequency=440, duration=1, amplitude=5000, sample_rate=44100):
    t = np.linspace(0, duration, int(sample_rate * duration), dtype=np.float32)
    wave = amplitude * np.sin(2 * np.pi * frequency * t)
    return wave

def play_sound(wave, sample_rate=44100):
    audio = sa.WaveObject(wave, 1, 2, sample_rate)
    play_obj = audio.play()
    play_obj.wait_done()

if __name__ == "__main__":
    wave = create_sine_wave()
    play_sound(wave)
1 Like

Cool idea to use the --target argument. :slight_smile: