A set of command line tools to help you keep your pip
-based packages fresh,
even when you've pinned them. You do pin them, right?
As part of a Python project's environment tooling (similar to pip
), it's
recommended to install pip-tools
in each project's virtual environment:
$ source /path/to/venv/bin/activate
(venv)$ pip install pip-tools
Note: all of the remaining example commands assume you've activated your project's virtual environment.
Suppose you have a Flask project, and want to pin it for production.
If you have a setup.py
with install_requires=['Flask']
, then run
pip-compile
without any arguments:
$ pip-compile
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --output-file requirements.txt setup.py
#
click==6.7 # via flask
flask==0.12.2
itsdangerous==0.24 # via flask
jinja2==2.9.6 # via flask
markupsafe==1.0 # via jinja2
werkzeug==0.12.2 # via flask
pip-compile
will produce your requirements.txt
, with all the Flask
dependencies (and all underlying dependencies) pinned. You should put
requirements.txt
under version control.
If you don't use setup.py
(it's easy to write one), you can create a
requirements.in
file to declare the Flask dependency:
# requirements.in
Flask
Now, run pip-compile requirements.in
:
$ pip-compile requirements.in
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --output-file requirements.txt requirements.in
#
click==6.7 # via flask
flask==0.12.2
itsdangerous==0.24 # via flask
jinja2==2.9.6 # via flask
markupsafe==1.0 # via jinja2
werkzeug==0.12.2 # via flask
And it will produce your requirements.txt
, with all the Flask dependencies
(and all underlying dependencies) pinned. You should put both
requirements.in
and requirements.txt
under version control.
If you would like to use Hash-Checking Mode available in pip
since
version 8.0, pip-compile
offers --generate-hashes
flag:
$ pip-compile --generate-hashes requirements.in
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --generate-hashes --output-file requirements.txt requirements.in
#
click==6.7 \
--hash=sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d \
--hash=sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b \
# via flask
flask==0.12.2 \
--hash=sha256:0749df235e3ff61ac108f69ac178c9770caeaccad2509cb762ce1f65570a8856 \
--hash=sha256:49f44461237b69ecd901cc7ce66feea0319b9158743dd27a2899962ab214dac1
itsdangerous==0.24 \
--hash=sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519 \
# via flask
jinja2==2.9.6 \
--hash=sha256:2231bace0dfd8d2bf1e5d7e41239c06c9e0ded46e70cc1094a0aa64b0afeb054 \
--hash=sha256:ddaa01a212cd6d641401cb01b605f4a4d9f37bfc93043d7f760ec70fb99ff9ff \
# via flask
markupsafe==1.0 \
--hash=sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665 \
# via jinja2
werkzeug==0.12.2 \
--hash=sha256:903a7b87b74635244548b30d30db4c8947fe64c5198f58899ddcd3a13c23bb26 \
--hash=sha256:e8549c143af3ce6559699a01e26fa4174f4c591dbee0a499f3cd4c3781cdec3d \
# via flask
To update all packages, periodically re-run pip-compile --upgrade
.
To update a specific package to the latest or a specific version use the
--upgrade-package
or -P
flag:
$ pip-compile --upgrade-package flask # only update the flask package
$ pip-compile --upgrade-package flask --upgrade-package requests # update both the flask and requests packages
$ pip-compile -P flask -P requests==2.0.0 # update the flask package to the latest, and requests to v2.0.0
If you use multiple Python versions, you can run pip-compile
as
py -X.Y -m piptools compile ...
on Windows and
pythonX.Y -m piptools compile ...
on other systems.
You might be wrapping the pip-compile
command in another script. To avoid
confusing consumers of your custom script you can override the update command
generated at the top of requirements files by setting the
CUSTOM_COMPILE_COMMAND
environment variable.
$ CUSTOM_COMPILE_COMMAND="./pipcompilewrapper" pip-compile requirements.in
#
# This file is autogenerated by pip-compile
# To update, run:
#
# ./pipcompilewrapper
#
flask==0.10.1
itsdangerous==0.24 # via flask
jinja2==2.7.3 # via flask
markupsafe==0.23 # via jinja2
werkzeug==0.10.4 # via flask
Now that you have a requirements.txt
, you can use pip-sync
to update
your virtual environment to reflect exactly what's in there. This will
install/upgrade/uninstall everything necessary to match the
requirements.txt
contents.
Be careful: pip-sync
is meant to be used only with a
requirements.txt
generated by pip-compile
.
$ pip-sync
Uninstalling flake8-2.4.1:
Successfully uninstalled flake8-2.4.1
Collecting click==4.1
Downloading click-4.1-py2.py3-none-any.whl (62kB)
100% |████████████████████████████████| 65kB 1.8MB/s
Found existing installation: click 4.0
Uninstalling click-4.0:
Successfully uninstalled click-4.0
Successfully installed click-4.1
To sync multiple *.txt
dependency lists, just pass them in via command
line arguments, e.g.
$ pip-sync dev-requirements.txt requirements.txt
Passing in empty arguments would cause it to default to requirements.txt
.
If you use multiple Python versions, you can run pip-sync
as
py -X.Y -m piptools sync ...
on Windows and
pythonX.Y -m piptools sync ...
on other systems.
Note: pip-sync
will not upgrade or uninstall packaging tools like
setuptools
, pip
, or pip-tools
itself. Use pip install --upgrade
to upgrade those packages.
As of v2.0.0, pip-tools has vendored pip v9.0.3
in its codebase.
This was done to keep pip-tools
working for users with pip v10.0.0
.
Only the pip-sync
command still use the pip
found in the virtualenv
,
and only for the pip install
and pip uninstall
commands issued as shell-outs
by pip-sync
.
- pipdeptree to print the dependency tree of the installed packages.