Skip to content

Add flag to automatically remove unused dependencies, like pip-autoremove #9118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
alexchandel opened this issue Nov 10, 2020 · 6 comments
Closed
Labels
resolution: duplicate Duplicate of an existing issue/PR

Comments

@alexchandel
Copy link

What's the problem this feature will solve?
Remove a package and its unused dependencies. Pip cannot do this.

Describe the solution you'd like
Automatically remove no-longer-used dependencies when uninstalling a package, via a flag like -r or --autoremove.

This would help declutter installations when removing packages with many dependencies, like jupyter-lab or tensorflow.

And it's easy to implement. pip-autoremove does it in <100 loc.

Alternative Solutions
The alternative is manually removing packages, or nuking the installation, which is not always possible.

Additional context
Example, an old jupyter-lab install's dependencies:

jupyterlab-server==1.0.7
  - jinja2 [required: >=2.10, installed: 2.11.1]
    - MarkupSafe [required: >=0.23, installed: 1.1.1]
  - json5 [required: Any, installed: 0.9.4]
  - jsonschema [required: >=3.0.1, installed: 3.2.0]
    - attrs [required: >=17.4.0, installed: 19.3.0]
    - importlib-metadata [required: Any, installed: 1.6.0]
      - zipp [required: >=0.5, installed: 3.1.0]
    - pyrsistent [required: >=0.14.0, installed: 0.16.0]
      - six [required: Any, installed: 1.14.0]
    - setuptools [required: Any, installed: 46.0.0]
    - six [required: >=1.11.0, installed: 1.14.0]
  - notebook [required: >=4.2.0, installed: 6.0.3]
    - ipykernel [required: Any, installed: 5.2.0]
      - appnope [required: Any, installed: 0.1.0]
      - ipython [required: >=5.0.0, installed: 7.13.0]
        - appnope [required: Any, installed: 0.1.0]
        - backcall [required: Any, installed: 0.1.0]
        - decorator [required: Any, installed: 4.4.2]
        - jedi [required: >=0.10, installed: 0.16.0]
          - parso [required: >=0.5.2, installed: 0.6.2]
        - pexpect [required: Any, installed: 4.8.0]
          - ptyprocess [required: >=0.5, installed: 0.6.0]
        - pickleshare [required: Any, installed: 0.7.5]
        - prompt-toolkit [required: >=2.0.0,<3.1.0,!=3.0.1,!=3.0.0, installed: 3.0.5]
          - wcwidth [required: Any, installed: 0.1.9]
        - pygments [required: Any, installed: 2.6.1]
        - setuptools [required: >=18.5, installed: 46.0.0]
        - traitlets [required: >=4.2, installed: 4.3.3]
          - decorator [required: Any, installed: 4.4.2]
          - ipython-genutils [required: Any, installed: 0.2.0]
          - six [required: Any, installed: 1.14.0]
      - jupyter-client [required: Any, installed: 6.1.2]
        - jupyter-core [required: >=4.6.0, installed: 4.6.3]
          - traitlets [required: Any, installed: 4.3.3]
            - decorator [required: Any, installed: 4.4.2]
            - ipython-genutils [required: Any, installed: 0.2.0]
            - six [required: Any, installed: 1.14.0]
        - python-dateutil [required: >=2.1, installed: 2.8.1]
          - six [required: >=1.5, installed: 1.14.0]
        - pyzmq [required: >=13, installed: 19.0.0]
        - tornado [required: >=4.1, installed: 6.0.4]
        - traitlets [required: Any, installed: 4.3.3]
          - decorator [required: Any, installed: 4.4.2]
          - ipython-genutils [required: Any, installed: 0.2.0]
          - six [required: Any, installed: 1.14.0]
      - tornado [required: >=4.2, installed: 6.0.4]
      - traitlets [required: >=4.1.0, installed: 4.3.3]
        - decorator [required: Any, installed: 4.4.2]
        - ipython-genutils [required: Any, installed: 0.2.0]
        - six [required: Any, installed: 1.14.0]
    - ipython-genutils [required: Any, installed: 0.2.0]
    - jinja2 [required: Any, installed: 2.11.1]
      - MarkupSafe [required: >=0.23, installed: 1.1.1]
    - jupyter-client [required: >=5.3.4, installed: 6.1.2]
      - jupyter-core [required: >=4.6.0, installed: 4.6.3]
        - traitlets [required: Any, installed: 4.3.3]
          - decorator [required: Any, installed: 4.4.2]
          - ipython-genutils [required: Any, installed: 0.2.0]
          - six [required: Any, installed: 1.14.0]
      - python-dateutil [required: >=2.1, installed: 2.8.1]
        - six [required: >=1.5, installed: 1.14.0]
      - pyzmq [required: >=13, installed: 19.0.0]
      - tornado [required: >=4.1, installed: 6.0.4]
      - traitlets [required: Any, installed: 4.3.3]
        - decorator [required: Any, installed: 4.4.2]
        - ipython-genutils [required: Any, installed: 0.2.0]
        - six [required: Any, installed: 1.14.0]
    - jupyter-core [required: >=4.6.1, installed: 4.6.3]
      - traitlets [required: Any, installed: 4.3.3]
        - decorator [required: Any, installed: 4.4.2]
        - ipython-genutils [required: Any, installed: 0.2.0]
        - six [required: Any, installed: 1.14.0]
    - nbconvert [required: Any, installed: 5.6.1]
      - bleach [required: Any, installed: 3.1.4]
        - six [required: >=1.9.0, installed: 1.14.0]
        - webencodings [required: Any, installed: 0.5.1]
      - defusedxml [required: Any, installed: 0.6.0]
      - entrypoints [required: >=0.2.2, installed: 0.3]
      - jinja2 [required: >=2.4, installed: 2.11.1]
        - MarkupSafe [required: >=0.23, installed: 1.1.1]
      - jupyter-core [required: Any, installed: 4.6.3]
        - traitlets [required: Any, installed: 4.3.3]
          - decorator [required: Any, installed: 4.4.2]
          - ipython-genutils [required: Any, installed: 0.2.0]
          - six [required: Any, installed: 1.14.0]
      - mistune [required: >=0.8.1,<2, installed: 0.8.4]
      - nbformat [required: >=4.4, installed: 5.0.5]
        - ipython-genutils [required: Any, installed: 0.2.0]
        - jsonschema [required: >=2.4,!=2.5.0, installed: 3.2.0]
          - attrs [required: >=17.4.0, installed: 19.3.0]
          - importlib-metadata [required: Any, installed: 1.6.0]
            - zipp [required: >=0.5, installed: 3.1.0]
          - pyrsistent [required: >=0.14.0, installed: 0.16.0]
            - six [required: Any, installed: 1.14.0]
          - setuptools [required: Any, installed: 46.0.0]
          - six [required: >=1.11.0, installed: 1.14.0]
        - jupyter-core [required: Any, installed: 4.6.3]
          - traitlets [required: Any, installed: 4.3.3]
            - decorator [required: Any, installed: 4.4.2]
            - ipython-genutils [required: Any, installed: 0.2.0]
            - six [required: Any, installed: 1.14.0]
        - traitlets [required: >=4.1, installed: 4.3.3]
          - decorator [required: Any, installed: 4.4.2]
          - ipython-genutils [required: Any, installed: 0.2.0]
          - six [required: Any, installed: 1.14.0]
      - pandocfilters [required: >=1.4.1, installed: 1.4.2]
      - pygments [required: Any, installed: 2.6.1]
      - testpath [required: Any, installed: 0.4.4]
      - traitlets [required: >=4.2, installed: 4.3.3]
        - decorator [required: Any, installed: 4.4.2]
        - ipython-genutils [required: Any, installed: 0.2.0]
        - six [required: Any, installed: 1.14.0]
    - nbformat [required: Any, installed: 5.0.5]
      - ipython-genutils [required: Any, installed: 0.2.0]
      - jsonschema [required: >=2.4,!=2.5.0, installed: 3.2.0]
        - attrs [required: >=17.4.0, installed: 19.3.0]
        - importlib-metadata [required: Any, installed: 1.6.0]
          - zipp [required: >=0.5, installed: 3.1.0]
        - pyrsistent [required: >=0.14.0, installed: 0.16.0]
          - six [required: Any, installed: 1.14.0]
        - setuptools [required: Any, installed: 46.0.0]
        - six [required: >=1.11.0, installed: 1.14.0]
      - jupyter-core [required: Any, installed: 4.6.3]
        - traitlets [required: Any, installed: 4.3.3]
          - decorator [required: Any, installed: 4.4.2]
          - ipython-genutils [required: Any, installed: 0.2.0]
          - six [required: Any, installed: 1.14.0]
      - traitlets [required: >=4.1, installed: 4.3.3]
        - decorator [required: Any, installed: 4.4.2]
        - ipython-genutils [required: Any, installed: 0.2.0]
        - six [required: Any, installed: 1.14.0]
    - prometheus-client [required: Any, installed: 0.7.1]
    - pyzmq [required: >=17, installed: 19.0.0]
    - Send2Trash [required: Any, installed: 1.5.0]
    - terminado [required: >=0.8.1, installed: 0.8.3]
      - ptyprocess [required: Any, installed: 0.6.0]
      - tornado [required: >=4, installed: 6.0.4]
    - tornado [required: >=5.0, installed: 6.0.4]
    - traitlets [required: >=4.2.1, installed: 4.3.3]
      - decorator [required: Any, installed: 4.4.2]
      - ipython-genutils [required: Any, installed: 0.2.0]
      - six [required: Any, installed: 1.14.0]

Enjoy pruning that by hand without breaking any other packages.

@McSinyx
Copy link
Contributor

McSinyx commented Nov 10, 2020

Note that in order to do this correctly, pip will need to have a database of which packages are automatically installed as dependencies. E.g. A depends on B and one initially needed A and B, then perse only needs B, so pip purge A shouldn't remove B.

@alexchandel
Copy link
Author

That would be a nice feature but it's unnecessary. pip uninstall already lacks that distinction. "autoremove"/"recursively remove" just means "recursively uninstall everything that would be come a leaf." Tracking manual installs & whitelisting them from removal sounds like a separate feature (a hack for this is to create a dummy package that depends on all manual installs).

@McSinyx
Copy link
Contributor

McSinyx commented Nov 13, 2020

That would be a nice feature but it's unnecessary.

I'd argue that not randomly breaking one's environment is much more than just a nice feature.

pip uninstall already lacks that distinction.

Because it's explicit. Whilst

"autoremove"/"recursively remove" just means "recursively uninstall everything that would be come a leaf."

is technically true, it's implicit, dangerous and unexpected (not how any package manager providing similar functionality does it). It might suit trying and removing programs/libraries in a working session (which can be done in virtual environments), yet for long-term management of end-user environments (as in where people install youtube-dl, thefuck, ect. and libraries for their local scripts), it's just asking for trouble.

I'm sure that there are many ways to track manual install, but as an user I insist that it must be done.

@uranusjr
Copy link
Member

I understand the feature can be nice for some, but pip maintainers take the blunt when some of the users find the feature to not fit their expectation. So new feature requests need to be thought through quite extensively before they can even be considered for acceptance. Tracking manual package installation is a hard problem (which may be unexepected), and most package managers resort to doing this the other way around, requiring the user to specify what are needed and purge the rest, which may be a better solution.

@uranusjr
Copy link
Member

The same rational has been spelled out in #2635. Although pip does have a proper resolver now, it is still lacking information required to do this properly, and may continue to lack them forever (since some of the features are arguably out of scope). I would recommend you looking into alternative project management tools instead, as mentioned in the linked issue.

@uranusjr
Copy link
Member

Marking as a duplicate to #5823.

@uranusjr uranusjr added the resolution: duplicate Duplicate of an existing issue/PR label Nov 13, 2020
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 7, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
resolution: duplicate Duplicate of an existing issue/PR
Projects
None yet
Development

No branches or pull requests

3 participants