It seems pip-tools is the exact tool you need to solve the problems you encountered in your development workflow.
pip-tools
enables you to specify your high-level dependencies (e.g. Django), while taking care automatically of your low-level dependencies (e.g. pytz). It also enables you to sync your environment to a requirements.txt
file, regardless of the messy state you might have.
Installing pip-tools
in your project
To use pip-tools
, first create a new empty Python virtual environment in your project and activate it, using the tool of your choice:
- with venv (built-in):
python3 -m venv .venv && source .venv/bin/activate
- with pyenv:
pyenv virtualenv 3.8.1 project-env && pyenv local project-env
Then, install pip-tools
in the Python virtual environment of your project:
Managing dependencies with pip-compile
using a requirements.in
file
pip-tools
includes a pip-compile
tool that takes a requirements.in
file as input. This requirements.in
file is similar to requirements.txt
, but it contains only high-level dependencies. For example, if your project is using the latest version of Django, you could write something like this in requirements.in
:
django>=3.0,<3.1
You can see that requirements.in
does not contain the dependencies of Django, only Django itself.
Once you have set your dependencies in requirements.in
, use pip-compile
to "compile" your requirements.in
into a requirements.txt
file:
➜ pip-compile requirements.in
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile requirements.in
#
asgiref==3.2.3 # via django
django==3.0.2
pytz==2019.3 # via django
sqlparse==0.3.0 # via django
The requirements.txt
file generated by pip-compile
indicates the source of every indirect dependency next to the package name. For example, pytz==2019.3
is a dependency of django
. In addition to that, it also pins each dependency to a precise version number, to make sure that the installation of your dependencies is reproducible
Applying dependencies from generated requirements.txt
with pip-sync
Now that you have a requirements.txt
, you can apply it on your Python virtual environment using pip-sync
:
➜ pip-sync requirements.txt
Collecting asgiref==3.2.3 (from -r /var/folders/r1/n_n031s51wz2gjwy7mb9k4rh0000gn/T/tmpvhv549si (line 1))
Using cached https://files.pythonhosted.org/packages/a5/cb/5a235b605a9753ebcb2730c75e610fb51c8cab3f01230080a8229fa36adb/asgiref-3.2.3-py2.py3-none-any.whl
Collecting django==3.0.2 (from -r /var/folders/r1/n_n031s51wz2gjwy7mb9k4rh0000gn/T/tmpvhv549si (line 2))
Using cached https://files.pythonhosted.org/packages/55/d1/8ade70e65fa157e1903fe4078305ca53b6819ab212d9fbbe5755afc8ea2e/Django-3.0.2-py3-none-any.whl
Collecting pytz==2019.3 (from -r /var/folders/r1/n_n031s51wz2gjwy7mb9k4rh0000gn/T/tmpvhv549si (line 3))
Using cached https://files.pythonhosted.org/packages/e7/f9/f0b53f88060247251bf481fa6ea62cd0d25bf1b11a87888e53ce5b7c8ad2/pytz-2019.3-py2.py3-none-any.whl
Collecting sqlparse==0.3.0 (from -r /var/folders/r1/n_n031s51wz2gjwy7mb9k4rh0000gn/T/tmpvhv549si (line 4))
Using cached https://files.pythonhosted.org/packages/ef/53/900f7d2a54557c6a37886585a91336520e5539e3ae2423ff1102daf4f3a7/sqlparse-0.3.0-py2.py3-none-any.whl
Installing collected packages: asgiref, pytz, sqlparse, django
Successfully installed asgiref-3.2.3 django-3.0.2 pytz-2019.3 sqlparse-0.3.0
pip-sync
will make sure your virtual environment corresponds exactly to what is defined in the requirements.txt
file by uninstalling and installing the relevant packages.
After your environment has been synced, make sure your project code works properly. If it does, commit requirements.in
and requirements.txt
into version control.
Reference
For more details, you can refer to the docs of pip-tools, or to the article of Hynek Schlawack: Python Application Dependency Management in 2018.