[Distutils] Request for comment: Proposal to change behaviour of pip install

Nathaniel Smith njs at pobox.com
Sat Jun 25 18:40:37 EDT 2016

On Sat, Jun 25, 2016 at 2:31 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> Thanks for putting that together. The assertion in the write-up that
> the proposed behaviour matches that of operating system level package
> managers doesn't sound right to me:
> $ sudo dnf install -q python
> Package python-2.7.11-5.fc24.x86_64 is already installed, skipping.
> (My system actually has a Python update pending, so the "-q" option is
> suppressing the output telling me about that, but either way, it
> doesn't make any local changes unless I use the update or upgrade
> subcommand or supply the "--best" upgrade strategy option to the
> install command)

Right -- this is partly my error, because I missed this earlier in the
discussion (didn't yum use to at least offer an interactive prompt to
upgrade or something instead? I guess it doesn't matter).

> As far as I am aware, apt-get install behaves the same way - if you
> only give a package name, and that package is already installed on the
> system, it won't do anything, even if a newer version of that
> component is available, and you need to use the "upgrade" subcommand
> instead to say "upgrade to the latest available version".

No, FWIW, apt-get acts like the proposed pip install. From the apt-get
man page (my emphasis):

           install is followed by one or more packages desired for
           installation *or upgrading*
           This is also the target to use if you want to upgrade one or more
           already-installed packages without upgrading every package you have
           on your system. Unlike the "upgrade" target, which installs the
           newest version of all currently installed packages, "install" will
           install the newest version of only the package(s) specified. Simply
           provide the name of the package(s) you wish to upgrade, and if a
           newer version is available, it (and its dependencies, as described
           above) will be downloaded and installed.

Personally I think this is better UX than the dnf approach. Let's take
a Bayesian approach :-). What people really want is software that
reads their mind and does what they mean. We can't read the user's
mind, but if they type 'pip install foo' and 'foo' is already
installed, then their mental state must have somehow prompted them to
think that this was a good thing to do, so we can make some inferences
about what they must be thinking. I think there are two main mental
states that might have led them to type this strange thing:

- they didn't know 'foo' was installed, so they expected 'pip install
foo' to install it from scratch, and leave them with the latest

- they knew 'foo' was installed, and they (mistakenly or not) believed
that 'pip install' acts like 'apt-get install' and this is the way to
upgrade to the latest version. (Maybe they believe this because they
are Ubuntu users, maybe because 'pip install' is the only command they
know and they are making a guess, whatever),

Either way, having 'pip install' go ahead and do the upgrade gives the
user what they were expecting.

It also reduces the state space: if 'pip install foo' has the
post-condition that it always leaves you with the latest version, then
that's much simpler to reason about then the version where it might
leave you with the latest version or it might not depending on what
other commands you might have run a year ago. And you don't have to
remember that if you really want to make sure you have the latest
version regardless of your starting state then that's 'pip install foo
|| pip upgrade foo', or some other special incantation. And of course
if you write the wrong thing it will work fine on your machine, but
then when your users try following your tutorial then it goes wrong...

Of course, there is a third mental state that the user might have been
in: that they didn't know whether 'foo' is installed, and they wanted
to guarantee that some version of 'foo' is installed, but they
genuinely didn't care what version that is, *and* they'd prefer to
keep an old version rather than upgrade. That's a fairly odd and
complicated mental state to be in, but I guess it does come up
sometimes (like in Ian's use case of writing automated sysadmin
scripts). I don't have any objection to making those semantics
*available*, but I think it's a bad idea to attach them to 'pip
install', since that's the obvious thing that new and non-expert users
will reach for, and new and non-expert users by definition do not have
that kind of complicated mental state. But it would make sense to me
to provide this functionality under an opt-in command specifically for
experts like 'pip require foo', or 'pip install --prefer-current foo'.


Nathaniel J. Smith -- https://vorpus.org

More information about the Distutils-SIG mailing list