Python programs often need to be run inside a venv in order to allow the use of packages from pypi.org. But creating and entering a venv before running a script is a barrier, especially if a python program has been written for use by people who are not particularly familiar with python.
So what i’d like is a new function in the standard venvmodule called something like venv.enter(), typically to be called at the start of execution. It would do nothing if we are already in a venv, otherwise it would create/update a venv, install a provided list of packages, then re-run the current program inside the venv.
This would allow python programs that use pypi.org packages, to be run directly without the user needing to know how to create and enter a venv.
Note that this would need to be in the standard library - it cannot be implemented as a package on pypi.org because one cannot generally install packages when not in a venv.
[One can use things like pipx to run scripts inside an automatically-created venv, but this requires installation of pipx first, and the user then has to use pipx run as a prefix.]
I have a module aptest/autovenv.py at main · ArtifexSoftware/aptest · GitHub that does most of what i need, but the implementation is necessarily quite clumsy:
- It needs to be copied into each project that uses it.
- To re-run the current program inside the venv, it uses
subprocess.run(shell=True)to run a command of the form. <venv>/bin/activate && python {shlex.join(sys.argv)}. This has various problems:shlexis posix-specific and doesn’t work properly on Windows.- [There is the
mslexpackage that provides shlex-style fns on Windows, but of course it is on pypi so cannot be installed/used before we are in a venv.] - It changes the pid.
- [One cannot simply exec
<venv>/bin/python ...because it doesn’t set PATH, which causes subtle problems if the script creates child processes.]
As i understand things, entering a venv is actually very simple - it just involves adding the venv’s bin directory to PATH, and setting VIRTUAL_ENV.
An implementation inside the standard venv module would know what settings to use for a given venv directory, so it could use os.execve() instead of subprocess.run(shell=1). This would avoid creating a child process and also avoid the need for shlex.join(), thus avoiding all of the limitations of autovenv.py.