Quick tip: running pip inside of a snap sandbox

Sometimes it’s handy when users can install additional pip dependencies inside of a snap’s sandbox. Doing this is quite easy:

The first step is to add pip as a python dependency:

parts:
  python:
    source: ""
    plugin: python
    python-packages:
      - pip

The second step is to add a pip command which runs it in “user” mode, so all packages are installed in $SNAP_USER_DATA.

apps:
  pip:
    command: python -m pip
    environment:
      PIP_USER: 1
    plugs:
      - network

After this you’re done! Now users can run <snapname>.pip install <pip-package> to install pip dependencies.

For a working example, take a look at the Arduino snap

5 Likes

This approach does not appear to work with the latest python plugin / core. The Arduino’s snap uses core18 where python interpreter is installed by snapcraft as an apt package.

With core20 onwards, snapcraft creates a venv and, thus, pip would refuse installing packages with PIP_USER set upon detection a virtual environment (i.e. when sys.base_prefix != sys.prefix). It cannot install packages to the venv’s default system location either as it is read only.

A possible workaround for the latest versions of the python plugin/snap base is to direct pip to using a writable location:

  pip:
    command: bin/python -m pip
    environment:
      PYTHONPATH: ${PYTHONPATH:+$PYTHONPATH:}$SNAP_USER_DATA/.local/venv/
      PIP_TARGET: $SNAP_USER_DATA/.local/venv
    plugs:
      - network

A more precise solution would be having a wrapper that modifies the sys.path only for the active python environment.

2 Likes