Search code examples
pythonpippython-packagingpython-wheel

How to install multiple .whl files in the right order


I have recently found myself in the situation of having to install all dependencies (20+) of a python project on a machine without internet connection. I used pip download ... to get all the *.whl files and transferred them manually. Only now I fully appreciate the genius of pip and how it figures out the dependency tree on its own and manages to install every package in the right order. E.g. a package depends on the requests package which on its own depends on the urllib3 package and so on.

I wanted an automated way to install all these dependencies on the machine using the command console or python itself, so I turned to StackOverflow and found these solutions: How to install multiple whl files in cmd

Nearly all suggested solutions work for me, however have the disadvantage of having to run them multiple times until no installation fails anymore! This is due to the scripts/commands sorting the packages alphabetically and trying to install them in that order (e.g. trying to install requests before urllib3 is in place).

Is there a smarter way to do this with only executing a script/command on time?


Solution

  • This directory full of wheel distribution files that you created is sometimes called a wheelhouse. They are often used to make repeatable and/or offline installations.

    A common way to install from a wheelhouse is:

    python -m pip install --no-index --no-deps path/to/wheelhouse/*.whl
    

    If all the wheels for all dependencies and their dependencies are in the wheelhouse, then the installation order does not matter and there is no need to connect to any remote package index (for dependency resolution, etc.). That is why we can use the --no-deps and --no-index flags.

    Reference:


    Aside:

    Only now I fully appreciate the genius of pip and how it figures out the dependency tree on its own and manages to install every package in the right order.

    pip's dependency resolver is resolvelib. There is a simple example on its source code repository showing how to use it to solve for wheels on PyPI.