My pet peeve: Wrangling with virtual environments for simple scripts.
peeve provides a virtual environment and runs your script in a single command:
peeve script.py
or with the shorter alias:
pv script.py
In detail, peeve will:
- Search for a
requirements.txt
- Create a virtual environment, if required
- Update the installed packages, if required
- Activate the virtual environment, if required
- Run the script
Alternatively, you can add
from peeve import bootstrap
before any third-party import and run the script the usual way:
python script.py
In our team we often provide Python scripts with our internal Git repositories to automate any kind of workflow. As soon as the scripts rely on third-party packages, things start to get complicated.
We all know that you shouldn't install Python packages globally.
However, creating virtual environment, activating it, and keeping the dependencies
up to date are a few steps too many if you just want to run a script.
You can easily forget to update the dependencies after a git pull
,
or to activate the virtual environment when you start a new shell session.
Even worse, the commands for activation depend on your shell and operating system.
While there are excellent tools like pipx, they typically require you to package your scripts. Especially for team members who are not Python experts because they develop in other languages are have other roles such as testers, this situation is challenging.
peeve is available on the Python Package Index:
pip install peeve
Since peeve does not have any third-party dependencies, a global installation is probably less harmful than usually. Still, you should prefer pipx if you only need the command line usage:
pipx install peeve
Since peeve is a single file with no dependencies, you can easily copy it into you project ("vendoring") or use a similar mechanism like Git subtrees or Git submodules.
Assuming you have a project with the following files:
script.py
requirements.txt
...
Use peeve
instead of python
to run your script:
peeve script.py
You may also use the shorter pv
alias:
pv script.py
If the peeve
command is not accesible, use:
python -m peeve script.py
It will:
- Create a virtual environment
.venv
, if not available. - Install the
requirements.txt
, if not up to date. - Pass the remaining arguments to the python interpreter of the venv.
If there is nothing to do, the startup is not much slower than the Python interpreter itself.
Add a single import line to your script:
# standard library imports
from peeve import bootstrap
# third-party imports
Then you can execute the script directly with the Python interpreter:
python script.py
You may need to replace python
by the appropriate command on your system.
In any case, Python must be able to import peeve
, so you must have it installed
globally, inside the current virtual environment, or have the peeve.py
script on
the Python search path.
peeve uses the Python interpreter it was invoked with. You can combine the Python launcher with peeve to select the desired Python version:
py -3.10 -m peeve script.py
Currently, peeve does not check the Python version in any way. If you call peeve with a different Pythin version than the one you used to create the virtual environment, you may encounter problems. In this case, delete the virtual environment and let peeve recreate it.
peeve uses pip and venv and is fully compatible to direct usage of those tools. This means that peeve can update and activate manually created virtual envionments, or that you can manually modify virtual environments created with peeve. However, peeve cannot detect such changes since they pypass the hashing mechanism.
peeve makes to assumptions about your project:
- you have a
requirements.txt
at the root of the project - you want to use a virtual environment
.venv
at the root of the project
Other requirement files or virtual environments are ignored.
You may use peeve from within an active virtual environment.
If the active environment is the desired .venv
one, peeve will continue to use it.
If it is a different one, peeve will switch to .venv
automatically.
Implemented:
- Single file, no external dependencies
- No configuration required
- No packaging of scripts required
- Dual usage: from command line or as import
- Dicovery of
requirements.txt
and existing.venv
in parent directory - Hashing of requirements to skip unnecessary upgrade
- Fast in-process venv activation and script execution
Planned:
- Awareness of parallel Python versions and/or operating systems
- Support for other interpreter modes (e.g.
-m
,-c
or interactive) - Configuration of requirements file location and/or venv location
- Support for other dependency specification formats
tox
is a much more powerful tool that can achieve a similar effect
if you invoke tox -- script.py
with the following tox.ini
:
[testenv]
skip_install = true
deps = -r requirements.txt
commands = python {posargs}
peeve
is faster and works without any configuration.
- Generate code coverage report
- Generate HTML documentation
- Setup CI
- Fix broken packaging
- Fix Linux/MacOS support
- Fix Python 3.7 support
- Initial release