How to make use of custom external Python modules in Blender or an add-on on Linux
update
I found out that the user-configuration folder for Blender, in ~/.config/blender/&lt;version&gt;/scripts/, though only containing   an addons folder by default, can have also a modules and a startup folder. If packages are pip-installed in the modules folder, they are visible from Blender, so, no custom virtualenv, or custom path manipulation at runtime is needed.

In other words, in a modern Linux, to have a Python package available for my user visible in Python's blender, I can do:

mkdir ~/.config/blender/2.79/scripts/modules
pip install -t ~/.config/blender/2.79/scripts/modules &lt;python-package&gt;


On Windows, the scripts folder for Blender will have a modules folder that can be used in the same way, as per the answers in the similar question here: Using 3rd party Python modules

previous answer

What I did do is a small Python function that is run prior to other imports in the add-on .py file to introspect the system Path and add any active virtualenv's to the Python import directory list sys.path.

The final function I came up with may be robust enough to help others. I add this to the beggining of my .py add-ons:

def fix_path():
    """Enable 3rd party Python modules installed in an
    active Virtualenv when Python is run.
    (Blender ignores the virtualenv, and uses a
    Python binary hardcoded in the build. This works
    if the virtualenv's Python is the same as blenders')
    """

    import sys, os
    from pathlib import Path

    pyversion_path = f"python{sys.version_info.major}.{sys.version_info.minor}"

    for pathcomp in os.environ["PATH"].split(os.pathsep)[::-1]:
        p = Path(pathcomp)
        if p.name != "bin":
            continue
        lib_path = p.parent / "lib" / pyversion_path / "site-packages"
        if not lib_path.exists():
            continue
        if str(lib_path) in sys.path:
            continue
        sys.path.insert(0, str(lib_path))

        print(f"{__name__} Add-on: prepended {lib_path!r} to PYTHONPATH")

fix_path()


(import statements follow)