44

I have Python wheel file: psutil-5.4.5-cp26-none-linux_x86_64.whl

How can I list the dependencies this wheel has?

guettli
  • 25,042
  • 81
  • 346
  • 663
  • Maybe you are looking for something like [this](https://stackoverflow.com/questions/42237072/list-dependencies-in-python)? – Billal Begueradj May 04 '18 at 08:37
  • @Begueradj not, the question you link is different. I want to extract the dependencies from the wheel file. The wheel is not installed yet. – guettli May 04 '18 at 09:04
  • I don't think you can do that. But you can create a virtualenv, install the package, and run `pip freeze`. – Erik Cederstrand May 04 '18 at 09:33
  • 3
    Actually, I just tried to unzip (not gunzip) a wheel I had lying around, and in the `packagename-version.dist-info/METADATA` file contains a list of `Requires-Dist:` entries that contain the compiled requirements from `setup.py`. – Erik Cederstrand May 04 '18 at 09:43
  • 1
    @ErikCederstrand thank you! If you write this as answer, then I will up-vote it. – guettli May 07 '18 at 07:02
  • 1
    You may try this `$ pip install pipdeptree` then `$ pipdeptree -fl`. – thewaywewere May 10 '18 at 17:03

7 Answers7

61

As previously mentioned, .whl files are just ZIP archives. You can just open them and poke around in the METADATA file.

There is a tool, however, that can make this manual process a bit easier. You can use pkginfo, which can be installed with pip.

CLI usage:

$ pip install pkginfo
$ pkginfo -f requires_dist psutil-5.4.5-cp27-none-win32.whl
requires_dist: ["enum34; extra == 'enum'"]

API usage:

>>> import pkginfo
>>> wheel_fname = "psutil-5.4.5-cp27-none-win32.whl"
>>> metadata = pkginfo.get_metadata(wheel_fname)
>>> metadata.requires_dist
[u"enum34 ; extra == 'enum'"]
wim
  • 338,267
  • 99
  • 616
  • 750
samu
  • 2,870
  • 16
  • 28
9

I just tried to unzip (not gunzip) a wheel package I had lying around. The packagename-version.dist-info/METADATA file contains a list of Requires-Dist: entries that contain the compiled requirements from setup.py.

Erik Cederstrand
  • 9,643
  • 8
  • 39
  • 63
3

You can install the wheel file in a separate virtual environment and then look which all other packages are installed.

Use pip freeze command to see all installed packages.

SHIVAM JINDAL
  • 2,844
  • 1
  • 17
  • 34
  • And this is the only way to see recursive requirements (packages required by other packages) with the `pip list` command. – glenfant May 12 '18 at 15:37
  • But that won't tell whether certain versions of the packages are required. – Roland Weber Feb 15 '21 at 09:58
  • @RolandWeber If a package is installed during installation of others that means it is required. – SHIVAM JINDAL Feb 15 '21 at 10:35
  • @SHIVAMJINDAL It means that the package is required, but you don't know if certain versions of the package are required or excluded. xyz==3.5.7, xyz>3.0, xyz<4.0a0, or just xyz are very different dependency specs. All of them could be satisfied by version 3.5.7, but most of them also by other versions. – Roland Weber Feb 16 '21 at 11:53
  • @RolandWeber It will tell you what version installed during the installation of the parent package. – SHIVAM JINDAL Feb 16 '21 at 21:02
  • @SHIVAMJINDAL The question isn't about what version gets installed. The question is about finding out the _requirements_ of a package. If you see that package xyz gets installed in version 3.5.7, that does not tell you what version of xyz is _required_. It only tells you that version 3.5.7 is one of possibly many versions that happen to satisfy the requirement. – Roland Weber Feb 18 '21 at 06:39
3

From the directory where you have unzipped your wheel file (change .whl to .zip and unzip) run the following in a shell at the command line:

grep --include=METADATA -rnw '.' -e "Requires-Dist"
P Moran
  • 1,624
  • 3
  • 18
  • 32
2

Here's a minimal snippet that doesn't require you to have any external tool (unzip, gzip or similars), so it should work in both *nix/windows:

wheeldeps.py:

import argparse
from zipfile import ZipFile

parser = argparse.ArgumentParser()
parser.add_argument('filename')
args = parser.parse_args()

archive = ZipFile(args.filename)
for f in archive.namelist():
    if f.endswith("METADATA"):
        for l in archive.open(f).read().decode("utf-8").split("\n"):
            if 'requires-dist' in l.lower():
                print(l)

Example:

> python wheeldeps.py psutil-5.4.5-cp27-cp27m-win_amd64.whl
Requires-Dist: enum34; extra == 'enum'  
BPL
  • 9,632
  • 9
  • 59
  • 117
1

I use to install my virtual envs with pipenv that installs pew as a requirement. pew lets you install temporary virual environments that are deleted as you exit those special virtual environments. So...

Make a new empty virtual environment and activate it on the fly:

pew mktmpenv -p /usr/bin/python3.6

Install your package:

pip install somedistro

See what are the requirements of your distro (as well as requirements of requirements...):

pip list

Deactivate and delete the temporary environment.

exit

In addition, temporary virtual environments are very useful at packaging tests.

glenfant
  • 1,298
  • 8
  • 9
0

This is an post I found somewhere. I copied everything and emailed myself so I don't have source for this answer but I think this might help. If anyone know the source, I will delete this post and link it to that post.

Installation
$ pip install --upgrade pip  # pip-tools needs pip==6.1 or higher (!)
$ pip install pip-tools
Example usage for pip-compile
Suppose you have a Flask project, and want to pin it for production. Write the following line to a file:

# requirements.in
Flask
Now, run pip-compile requirements.in:

$ pip-compile requirements.in
#
# This file is autogenerated by pip-compile
# Make changes in requirements.in, then run this to update:
#
#    pip-compile requirements.in
#
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
And it will produce your requirements.txt, with all the Flask dependencies (and all underlying dependencies) pinned. Put this file under version control as well and periodically re-run pip-compile to update the packages.

Example usage for pip-sync
Now that you have a requirements.txt, you can use pip-sync to update your virtual env to reflect exactly what's in there. Note: this will install/upgrade/uninstall everything necessary to match the requirements.txt contents.

$ 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

The requirement.txt will have all the requirement needed for the package.

Sam
  • 1,206
  • 2
  • 12
  • 27
  • I gave up using `pip-tools` in favour of `pipenv` that does a better job in that firld (close to what npm does for Javascript). – glenfant May 12 '18 at 15:57