ChatGPT解决这个技术问题 Extra ChatGPT

How to pip install a package with min and max version range?

I'm wondering if there's any way to tell pip, specifically in a requirements file, to install a package with both a minimum version (pip install package>=0.2) and a maximum version which should never be installed (theoretical api: pip install package<0.3).

I ask because I am using a third party library that's in active development. I'd like my pip requirements file to specify that it should always install the most recent minor release of the 0.5.x branch, but I don't want pip to ever try to install any newer major versions (like 0.6.x) since the API is different. This is important because even though the 0.6.x branch is available, the devs are still releasing patches and bugfixes to the 0.5.x branch, so I don't want to use a static package==0.5.9 line in my requirements file.

Is there any way to do that?


L
Leif Arne Storset

You can do:

$ pip install "package>=0.2,<0.3"

And pip will look for the best match, assuming the version is at least 0.2, and less than 0.3.

This also applies to pip requirements files. See the full details on version specifiers in PEP 440.


For the record, I think "package>=0.2,<=0.3" doesn't make a lot of sense: when would you be okay with both 0.2 and 0.3.0, but not with any of 0.3's bugfix releases? I think "package>=0.2,<0.3" is a much better example, because it reflects the common case of saying: "please give me the latest bugfix release of the current minor version, but don't automatically upgrade me to the next minor version, because I would like to do that explicitly, making sure that there are no functional changes affecting me."
If you like this answer, you'll love Mortiz answer right down below! Be sure to check it out, ~=0.2 is (imho) a better solution than this.
@BradRoot It's really unclear what ~=0.2.1 would do, for example. Being explicit as in >=0.2,<0.3 is a good thing because it's really clear what's happening.
@Acumenus someone who understands the properties of the requirement format and how versioning works wouldn't write ~=0.2.1 in a requirements file. That's user error, not a disadvantage of the ~= prefix.
@BradRoot Wouldn't ~=0.2.1 mean >=0.2.1,<0.3? How is it a user error?
l
lowrin

you can also use:

pip install package==0.5.*

which is more consistent and easy to read.


This is a much better way to manage requirements.txt IMO. Using package==1.* instead of package>=1.2 prevents pip from installing major version 2+ for the package, which is desirable since major version changes are often backwards incompatible.
Note, This doesn't upgrade an existing package. e.g. if you have 0.5.1 installed, but 0.5.2 is latest, and you run install 0.5.* it will say "already satisfied" and leave you with 0.5.1. Adding --upgrade solves it.
This does not work for me pip install matplotlib==3.2.* zsh: no matches found: matplotlib==3.2.*
@Tillus the star sign is being expanded by zsh (just like when you execute rm myfiles*. You need to escape the argument, e.g with single quotes pip install 'matplotlib==3.2.*'.
M
Moritz

An elegant method would be to use the ~= compatible release operator according to PEP 440. In your case this would amount to:

package~=0.5.0

As an example, if the following versions exist, it would choose 0.5.9:

0.5.0

0.5.9

0.6.0

For clarification, each pair is equivalent:

~= 0.5.0
>= 0.5.0, == 0.5.*

~= 0.5
>= 0.5, == 0.*

@Mike'Pomax'Kamermans You should use ~=2.2.0 in that case(* operator will not work if you're using ~=). 2.2 and 2.2.0 (and 2.2.0.0, and so on) are internally handled as same thing when it comes to installing packages.
It is extremely unclear how this works for nested version numbering, e.g. ~=1.2.3. It is a lot more explicit and clearer to use the multi-clause form instead.
@MitchMcMabers That only works if the features you want happen to have been present in the first release of that major version, which isn't true in general. If you're relying on something that was added in v1.2.0, for example, == 1.* will improperly accept v1.1.0. The ~= (or >= plus < if you find that hard to read) operator is better because it encourages being correctly specific.
@Maxpm That's a good point. So == 1.* would fail and do nothing if we need a 1.2 version feature but the user already had 1.1 installed. Your proposed ~= 1.2 is the same as saying >= 1.2, < 2.0 (or >= 1.2, == 1.*). So yeah you're right, ~= is the best operator since it lets you target the development version you used of a library, while allowing newer versions within the same major version. Thanks for that clarification!
It seems really odd to me that numpy~=1.17.0 downloads 1.17.5, but numpy~=1.17 downloads 1.18.5.
D
Darius

nok.github.io/pipdev is an interactive tool for developers to test defined specifiers for version handling.

https://i.stack.imgur.com/mbkzt.png

Related to the question: nok.github.io/pipdev?spec=~=0.5.0&vers=0.6