How to make venv completely portable?

Viewed 2346

I want to create a venv environment (not virtualenv) using the following commands:

sudo apt-get install python3.8-venv
python3.8 -m venv venv_name
source venv_name/bin/activate

But it seems to be that it contains dependency on the system where it is created and it creates problems whenever I want to make it portable. That means, I want when I copy this folder along with my project and run it in another machine, it will work without making any changes.

But I am unable to activate the environment (it gets activated but the interpreter still uses system's python and pip.

Therefore, I tried making another venv in the second computer and copied the lib and lib64 folders from the older venv to this newer venv (without replacing existing files) but getting the following error this time:

File "/usr/local/lib/python3.8/ctypes/__init__.py" line 7, in <module>
    from _ctypes import Union, Structure, Array
ModuleNotFoundError: No module named '_ctypes'

But interesting thing is, if you notice, the newly created venv in the new machine also searching the missing package in its local directory and not in the venv.

How do I make the venv portable along with all its dependencies and reliably deploy in another device just by activating it?

1 Answers

Disclaimer: None of this is my work, I just found this blog-post and will briefly summarize: https://aarongorka.com/blog/portable-virtualenv/ archived

Caveat: This only works (semi-reliably) among Linux machines. Don't use in production!

The first step is to get copies of your python-executables in the venv/bin folder, so be sure to specify --copies when creating the virtual environment:

python3 -m venv --copies venv

All that's left seems to be changing the hardcoded absolute paths into relative paths, using your tool of choice. In the blogpost, they use pwd after changing to the venv-parent-directory whenever venv/bin/activate is run.

sed -i '43s/.*/VIRTUAL_ENV="$(cd "$(dirname "$(dirname "${BASH_SOURCE[0]}" )")" && pwd)"/' venv/bin/activate

Then, similarly all pip-scripts need to be adapted to run execution with the local python

sed -i '1s/./#!/usr/bin/env python/' venv/bin/pip

BUT, the real problem starts when installing new modules. I would expect most modules to behave nicely, but there will be those that hardcode expected path-structures or similarly thwart any work towards replacing path dependencies.

However: I find this trick is very useful to share a single folder among developers for finding elusive bugs.

Related