Pip: Revisit displaying setuptools in `pip freeze`?

Created on 26 Jan 2017  路  16Comments  路  Source: pypa/pip

Given the frustration with setuptools 34 is it perhaps a good time to reconsider the display of setuptools in pip freeze? At least at $work, it is a strong suggestion to _pin everything_ in applications (you can see our full set of tooling here), even setuptools / pip / wheel for repeatable builds -- perhaps setuptools and its new dependencies should be included as well (without needing our own implementation of pip freeze which includes them).

freeze enhancement

Most helpful comment

Given that post-PEP 517, we're gonna have no special casing for setuptools or even wheel, I'm a +1 to @ivoz's suggestion, if it's not implemented yet.

All 16 comments

Is pip freeze --all what you're looking for?

I'm suggesting that setuptools be excluded from the non---all output.

I don't think in a general case, setuptools deserves a special case over the other items there (pip, wheel, distribute), so I'd equivocate that to suggesting that the--all option be removed together and be made the default.

pip list already displays setuptools by default.

Given that post-PEP 517, we're gonna have no special casing for setuptools or even wheel, I'm a +1 to @ivoz's suggestion, if it's not implemented yet.

I'm gonna assign this to myself but if anyone wants to try their hand at this before I get too, you're more than welcome to do so.

I've been suggesting pip freeze --all for as long as I can remember now -- maybe we should make that the default?

I also agree that it would make sense for pip freeze to also output setuptools & wheel version (especially post-PEP 517 as Pradyun mentionned), but I'm more ambivalent with pip version.

The other question is how should we handle the transition ?

  • simply add a .removal changelog stating those packages are not excluded from freeze anymore and suggest to | grep -vE "^(pip|wheel|setuptools)=" to simulate the previous behavior ?
  • make --all the default (if we want to also output pip version) and add a new --legacy option for a few releases ?

At least, removing the --all option would help for #7157 ^^

I see the problem entirely the other way around. All the issues linked in OP have one common trait: they are all using a very old version of pip (or some installation that鈥檚 even older). Recent versions of pip do not cause the frustration, and adding setuptools to pip freeze helps none of those affected because they would never see that new behaviour. So IMO

  1. pip should include pip itself into pip freeze.
  2. Setuptools can include some kind of (semi-permanent) safty net in setup.py to hint how people using legacy pip to resolve the problem when it inevitably breaks their obsolete setup.

Edit to clarify: I don鈥檛 object to including setuptools in pip freeze (because PEP 517), but only don鈥檛 think that would solve the majority of the problem linked above.

New transition plan

Phase 1:

  • add an --exclude cumulative option to pip freeze and pip list (pip freeze --exclude pip --exclude setuptools): this will allow users to explicitly configure their pip to do what they want
    [freeze] exclude = pip setuptools
  • add a deprecation warning when using pip freeze without --all or any --exclude option stating that --all will soon be the default

Phase 2:

  • make --all the default
  • deprecate --all option that now does nothing.

All approaches here feel weird to me right now. That isn't to say that we shouldn't pick any of them, but is mostly just me stating my thoughts.


With the above transition plan, we'd create busy-work for users who want to constantly "do the right thing" and address warnings they get from the tool.

  • User X uses pip freeze today.
  • After updating to pip [v1], they see a deprecation warning that says "hey, --all is gonna be the default soon". They add --all to the invocation, and it silences that warning.
  • After updating to pip [v2], they now see a different deprecation warning that says "hey, --all is useless now". They now have to remove --all from the invocation to silence the warning.

I don't imagine most folks care about this additional pinning -- they won't see see any direct benefits from this change and we eat into a bit of our "churn budget".


9068 also feels weird, partly because I think it's a good idea. I guess the only thing it's missing is an escape hatch -- as proposed here to be called --exclude (which I really like BTW). It's also at odds with our deprecation policy -- I definitely think our policy is good since Hyrum's Law applies.

It feels like the best approach might be "make a breaking change without much noise, and properly communicate/fix things", and I really don't want to say "let's do that". :(

As a middle ground, I've pushed https://github.com/pypa/pip/pull/9073/files which implement Phase 1 without the warning.

@xavfernandez I have mixed feeling with this idea of making --all the default. (sorry to be late to the party)

In most cases, applications that are installed in a virtualenv do not depend on pip, setuptools nor wheel, so it is not necessary to include these in pinned requirements.

When you do, and use freeze --all > requirements.txt, and commit requirements.txt to source control, what typically happens is

  • a developer obtains the code, and creates a virtualenv: this usually installs a recent pip, wheel, and setuptools
  • pip install -r requirements: this first run uses the recent pip to do the installation, which downgrades it to the version in requirements.txt
  • subsequent use of pip in the virtualenv therefore uses a different version than the one that was used for the first install

So the pinning of pip, setuptools and wheel is actually misleading because on the initial install from requirements.txt in a fresh venv, it has no effect.

OTOH when the application depends on setuptools or wheel (or pip), not freezing them by default is incorrect.

What would be more natural IMO, is that pip freeze includes setuptools, wheel, or pip only when they are dependencies of another installed distribution.

I remained vague in https://github.com/pypa/pip/pull/9073/files#diff-429186493476e02aaccfb73ba9d42328c0a6b04528054a8a42ca4de2b11e9b6a by mentioning a future version, this could easily be a year or more :)
Hopefully, this might leave time for users to explicitly switch to --exclude if that is what they want and/or for us to cleverly nudge them to do so.

With the generalization of PEP-517, I'm hopeful the inclusion of setuptools & wheel will be less and less of a problem (albeit slowly) but I agree that pip will always be a special snowflake and I don't really see a way around that (should pip warn the user when changing its own version with other packages ? WARNING: pip is going to update to pip XX but the current install will still be running with pip YY. If the install needs to run with pip YY, please update pip first. ?)

What would be more natural IMO, is that pip freeze includes setuptools, wheel, or pip only when they are dependencies of another installed distribution.

I agree that this would be somewhat "cleaner" but it would also mean:

$ pip freeze
setuptools==50.3.2
setuptools-scm==4.1.2
$ pip uninstall setuptools-scm -yq
$ pip freeze

and I would not call this "natural" ^^

I would not call this "natural" ^^

Hm... yes, maybe trying to be that smart is out of scope for pip freeze indeed, and that should be the role of higher level tools that know more about the user intent and context.

Isn't the big problem here that virtualenv installs setuptools and wheel? If it weren't for that, project environments would only ever contain the packages that the project actually depended on, and build dependencies would be in pyproject.toml.

So maybe we should do something like:

  1. Use --all outside of a virtual environment.
  2. Within a virtual environment, exclude whatever virtualenv (or venv, if the environment was created by venv鹿) installs by default.

Yes, this is awkward, but with isolated builds, there should be no reason to install build tools in environments anyway. So we're working round other projects' (incorrect?) ideas of what "everyone needs" - which is always awkward...

鹿 And maybe we need to consider conda environments as another case 馃檨

Was this page helpful?
0 / 5 - 0 ratings