A *developer package list" is a list contains only packages used in applicatoin codes. without dependencies of these packages.
For example, you import package A and X in your codes,
while A depends on B, B depends on C, and X depends on Y,
Y depends on Z.
When you run pip freeze
, you can see A, B, C, X, Y, Z,
and their versions.
But what we care is A and X. What we wanna say is "use whatever packages to make A and X work". Here our *developer packages list" contains only A and X.
On the other hand, versions of some dependency packages do matter. For example, there's a compatible problem between IPython v7.19 and jedi (depend by IPython) v0.18. Use latest version (as of 2021.1.21) of these two packages will crash IPython console when TAB-completing. To fix it, we need downgrade jedi to 0.17.2.
As Pipenv: A Guide to the New Python Packaging Tool asked:
How do you allow for deterministic builds for your Python project without gaining the responsibility of updating versions of sub-dependencies?
For Developing-only Project
To fulfill both targets, we need install package with pip
, remove package with
pip-autoremove,
inspect current status of packages with pipdeptree.
pipdeptree produces full requirements.txt (with pipdeptree -f
) like this:
jupyter==1.0.0
ipykernel==5.4.3
ipython==7.19.0
backcall==0.2.0
decorator==4.4.2
jedi==0.17.2
parso==0.7.1
This file serves two purposes:
- Used as a traditional requirements.txt fed to
pip install
; - Used as a developer-friendly packages list (like the one created by
pip-chill
) simply withgrep '^\w' requirements.txt
.
Now no matter how many pip install
are executed in your project,
run pipdeptree -f | grep '^\w'
to get the developer package list.
Remove unnecessary package with pip-autoremove <package-name>
to get rid of
any orphan (dangling) packages.
Note:
pip-chill is another option. However it can only serves the 2nd purpose, for the requirements.txt it produces is like this::
jupyter==1.0.0
pip-autoremove==1.0.1
pipdeptree==2.0.0
pyqt5==5.15.2
seaborn==0.11.1
sklearn==0.0
statsmodels==0.12.1
Developing & Deploying Project
In above list, packages for production (like sklearn, seaborn), for developing (like jupyter), and for maintaining (like pipdeptree) are save in the same list file: requirements.txt. This is OK for developing-only project.
But when deploy an application to end user, it's a good practice to only package production packages, while leave developing and maintaining tools out of the final application. That's where poetry or pipenv comes in.
These tools distinguishes user file (pyproject.toml
for poetry,
or Pipfile
for pipenv, for avoiding "updating versions of sub-dependencies" manually)
and lock file (poetry.lock
and Pipfile.lock
, for "deterministic builds ").