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?
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.
you can also use:
pip install package==0.5.*
which is more consistent and easy to read.
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.
pip install matplotlib==3.2.*
zsh: no matches found: matplotlib==3.2.*
rm myfiles*
. You need to escape the argument, e.g with single quotes pip install 'matplotlib==3.2.*'
.
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.*
~=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.
~=1.2.3
. It is a lot more explicit and clearer to use the multi-clause form instead.
== 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.
== 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!
numpy~=1.17.0
downloads 1.17.5, but numpy~=1.17
downloads 1.18.5.
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
Success story sharing
"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."~=0.2
is (imho) a better solution than this.~=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.~=0.2.1
in a requirements file. That's user error, not a disadvantage of the~=
prefix.~=0.2.1
mean>=0.2.1,<0.3
? How is it a user error?