|
| 1 | +# Dependency Resolution |
| 2 | + |
| 3 | +pip is capable of determining and installing the dependencies of packages. The |
| 4 | +process of determining which version of a dependency to install is known as |
| 5 | +dependency resolution. This behaviour can be disabled by passing |
| 6 | +{any}`--no-deps` to {any}`pip install`. |
| 7 | + |
| 8 | +## How it works |
| 9 | + |
| 10 | +When a user does a `pip install` (e.g. `pip install tea`), pip needs to work |
| 11 | +out the package's dependencies (e.g. `spoon`, `hot-water`, `tea-leaves` etc.) |
| 12 | +and what the versions of each of those dependencies it should install. |
| 13 | + |
| 14 | +At the start of a `pip install` run, pip does not have all the dependency |
| 15 | +information of the requested packages. It needs to work out the dependencies |
| 16 | +of the requested packages, the dependencies of those dependencies, and so on. |
| 17 | +Over the course of the dependency resolution process, pip will need to download |
| 18 | +distribution files of the packages which are used to get the dependencies of a |
| 19 | +package. |
| 20 | + |
| 21 | +## Backtracking |
| 22 | + |
| 23 | +```{versionchanged} 20.3 |
| 24 | +pip's dependency resolver is now capable of backtracking. |
| 25 | +``` |
| 26 | + |
| 27 | +During dependency resolution, pip needs to make assumptions about the package |
| 28 | +versions it needs to install and, later, check these assumptions were not |
| 29 | +incorrect. When pip finds that an assumption it made earlier is incorrect, it |
| 30 | +has to backtrack, which means also discarding some of the work that has already |
| 31 | +been done, and going back to choose another path. |
| 32 | + |
| 33 | +This can look like pip downloading multiple versions of the same package, |
| 34 | +since pip explicitly presents each download to the user. The backtracking of |
| 35 | +choices made during is not unexpected behaviour or a bug. It is part of how |
| 36 | +dependency resolution for Python packages works. |
| 37 | + |
| 38 | +````{admonition} Example |
| 39 | +The user requests `pip install tea`. The package `tea` declares a dependency on |
| 40 | +`hot-water`, `spoon`, `cup`, amongst others. |
| 41 | +
|
| 42 | +pip starts by picking the most recent version of `tea` and get the list of |
| 43 | +dependencies of that version of `tea`. It will then repeat the process for |
| 44 | +those packages, picking the most recent version of `spoon` and then `cup`. Now, |
| 45 | +pip notices that the version of `cup` it has chosen is not compatible with the |
| 46 | +version of `spoon` it has chosen. Thus, pip will "go back" (backtrack) and try |
| 47 | +to use another version of `cup`. If it is successful, it will continue onto the |
| 48 | +next package (like `sugar`). Otherwise, it will continue to backtrack on `cup` |
| 49 | +until it finds a version of `cup` that is compatible with all the other |
| 50 | +packages. |
| 51 | +
|
| 52 | +This can look like: |
| 53 | +
|
| 54 | +```console |
| 55 | +$ pip install tea |
| 56 | +Collecting tea |
| 57 | + Downloading tea-1.9.8-py2.py3-none-any.whl (346 kB) |
| 58 | + |████████████████████████████████| 346 kB 10.4 MB/s |
| 59 | +Collecting spoon==2.27.0 |
| 60 | + Downloading spoon-2.27.0-py2.py3-none-any.whl (312 kB) |
| 61 | + |████████████████████████████████| 312 kB 19.2 MB/s |
| 62 | +Collecting cup>=1.6.0 |
| 63 | + Downloading cup-3.22.0-py2.py3-none-any.whl (397 kB) |
| 64 | + |████████████████████████████████| 397 kB 28.2 MB/s |
| 65 | +INFO: pip is looking at multiple versions of this package to determine |
| 66 | +which version is compatible with other requirements. |
| 67 | +This could take a while. |
| 68 | + Downloading cup-3.21.0-py2.py3-none-any.whl (395 kB) |
| 69 | + |████████████████████████████████| 395 kB 27.0 MB/s |
| 70 | + Downloading cup-3.20.0-py2.py3-none-any.whl (394 kB) |
| 71 | + |████████████████████████████████| 394 kB 24.4 MB/s |
| 72 | + Downloading cup-3.19.1-py2.py3-none-any.whl (394 kB) |
| 73 | + |████████████████████████████████| 394 kB 21.3 MB/s |
| 74 | + Downloading cup-3.19.0-py2.py3-none-any.whl (394 kB) |
| 75 | + |████████████████████████████████| 394 kB 26.2 MB/s |
| 76 | + Downloading cup-3.18.0-py2.py3-none-any.whl (393 kB) |
| 77 | + |████████████████████████████████| 393 kB 22.1 MB/s |
| 78 | + Downloading cup-3.17.0-py2.py3-none-any.whl (382 kB) |
| 79 | + |████████████████████████████████| 382 kB 23.8 MB/s |
| 80 | + Downloading cup-3.16.0-py2.py3-none-any.whl (376 kB) |
| 81 | + |████████████████████████████████| 376 kB 27.5 MB/s |
| 82 | + Downloading cup-3.15.1-py2.py3-none-any.whl (385 kB) |
| 83 | + |████████████████████████████████| 385 kB 30.4 MB/s |
| 84 | +INFO: pip is looking at multiple versions of this package to determine |
| 85 | +which version is compatible with other requirements. |
| 86 | +This could take a while. |
| 87 | + Downloading cup-3.15.0-py2.py3-none-any.whl (378 kB) |
| 88 | + |████████████████████████████████| 378 kB 21.4 MB/s |
| 89 | + Downloading cup-3.14.0-py2.py3-none-any.whl (372 kB) |
| 90 | + |████████████████████████████████| 372 kB 21.1 MB/s |
| 91 | +``` |
| 92 | +
|
| 93 | +These multiple `Downloading cup-{version}` lines show that pip is backtracking |
| 94 | +choices it is making during dependency resolution. |
| 95 | +```` |
| 96 | + |
| 97 | +If pip starts backtracking during dependency resolution, it does not know how |
| 98 | +many choices it will reconsider, and how much computation would be needed. |
| 99 | + |
| 100 | +For the user, this means it can take a long time to complete when pip starts |
| 101 | +backtracking. In the case where a package has a lot of versions, arriving at a |
| 102 | +good candidate can take a lot of time. The amount of time depends on the |
| 103 | +package size, the number of versions pip must try, and various other factors. |
| 104 | + |
| 105 | +Backtracking reduces the risk that installing a new package will accidentally |
| 106 | +break an existing installed package, and so reduces the risk that your |
| 107 | +environment gets messed up. To do this, pip has to do more work, to find out |
| 108 | +which version of a package is a good candidate to install. |
0 commit comments