Skip to content

User-installed Python modules do not have precedence over those pre-installed in the snap #167

Open
@furgo16

Description

@furgo16

The snap comes with a series of Python modules preinstalled, which on the host system are installed at:

/snap/freecad/current/usr/lib/python3.10/dist-packages/$MODULE

The user can install new Python modules using the provided freecad.pip command. Those modules are then installed at:

$HOME/snap/freecad/common/.local/lib/python3.10/site-packages/$MODULE

Sometimes it is useful for one of the preinstalled Python modules (e.g. ifcopenshell) to be upgraded. Be it to fix a bug, or to use a new feature. This works in principle. E.g.

freecad.pip install ifcopenshell

As expected, we then end up with:

/snap/freecad/current/usr/lib/python3.10/dist-packages/ifcopenshell         # The version we just installed: 0.8.1
$HOME/snap/freecad/common/.local/lib/python3.10/site-packages/ifcopenshell  # The preinstalled version: 0.8.0

If we then import ifcopenshell from the Python console within FreeCAD:

>>> import ifcopenshell
>>> ifcopenshell.__version__
'0.8.0'

Notice how FreeCAD's Python only saw the preinstalled version. When the snap is launched, a message seems to indicate that the user path is searched for before the system path:

Adding snap-specific PYTHONPATH to sys.path: $HOME/snap/freecad/common/.local/lib/python3.10/site-packages:/snap/freecad/1296/lib/python3.10/site-packages:/snap/freecad/1296/usr/lib/python3/dist-packages

pythonpath = os.environ.get("SNAP_PYTHONPATH")
if pythonpath:
print(f"Adding snap-specific PYTHONPATH to sys.path: {pythonpath}")
os.environ["PYTHONPATH"] = pythonpath
for path in pythonpath.split(":"):
sys.path.insert(0, path)

However, that does not seem to be the case.

Running:

>>> import sys
>>> print(sys.path)

Returns PYTHONPATH, of which here's an edited extract:

/snap/freecad/1296/usr/lib/python3/dist-packages
/snap/freecad/1296/lib/python3.10/site-packages
$HOME/freecad/common/.local/lib/python3.10/site-packages
$HOME/freecad/common/.local/lib/python3.10/site-packages  # <= Injected by $SNAP_PYTHONPATH?
/snap/freecad/1296/usr/local/lib/python3.10/dist-packages # <= Injected by $SNAP_PYTHONPATH?
/snap/freecad/1296/usr/lib/python3/dist-packages          # <= Injected by $SNAP_PYTHONPATH?
$HOME/freecad/common/AdditionalPythonPackages/py310
$HOME/freecad/common/AdditionalPythonPackages
$HOME/freecad/common/
$HOME/freecad/common
$/snap/freecad/1296/lib/python3.10/site-packages/ifcopenshell/lib/linux/64bit/python3.10

Notice how /snap/freecad/1296/usr/lib/python3/dist-packages is listed first, instead of $HOME/freecad/common/.local/lib/python3.10/site-packages

Running this snippet from FreeCAD's Python console:

>>> import os
>>> pythonpath = os.environ.get("SNAP_PYTHONPATH")
>>> pythonpath
'$HOME/snap/freecad/common/.local/lib/python3.10/site-packages:/snap/freecad/1296/lib/python3.10/site-packages:/snap/freecad/1296/usr/lib/python3/dist-packages'

That list of paths seems to be injected somewhere in the middle of the PYTHONPATH. Since it's inserted after /snap/freecad/1296/usr/lib/python3/dist-packages, it has no effect. Also note that SNAP_PYTHONPATH is a custom environment variable that we define in snapcraft.yaml:

PYTHONPATH: &pypath $PYTHONUSERBASE/lib/python3.10/site-packages:$SNAP/lib/python3.10/site-packages:$SNAP/usr/lib/python3/dist-packages
SNAP_PYTHONPATH: *pypath

In summary, Python packages are forever pinned to the version preinstalled with the snap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions