-
Notifications
You must be signed in to change notification settings - Fork 3k
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
"Detected a distutils installed project" is fatal in pip 8 #3384
Comments
Just a bit of background here: The fundamental problem is that "pure" distutils projects (ones that import distutils rather than setuptools, and which were not installed in a way to force setuptools to be injected, as pip does) when installed do not include all of the relevant metadata. They include information like "foobar v1.0" was installed but they do not include This generally "works", however it can lead to really weird, strange errors where you end if with Long term projects should stop importing from distutils and switch instead to just unconditionally importing from setuptools. This is the recommended way to function and in 2016 you're almost always guaranteed to have setuptools available on an end users's machine. We may elect to work around it and push the date for this back further, but realistically things need to stop relying on plain distutils. |
Hit this issue with installing
Worked around it by |
+1 on not lying to people that we know how to uninstall something when we really don't - literally the reason everyone stopped using |
Adding to 8.0.1 milestone, we should at least figure out what our answer is going to be before we release 8.0.1. |
Can we not as a minimum add something to the message saying "If you wish to uninstall FOO you need to manually identify and delete the files associated with the project from site-packages."? That seems like a better workaround than having people downgrade pip... |
So I have no doubt everyone understands the issue; but I am seeing something that's easier to reproduce than nebulous devstack jobs. On Ubuntu Trusty the problem is I think coming out of #1570 and that argparse is kind of in the virtualenv and kind of not (it's filtered, i think?)
this has now turned into an error
So it seems "outside environment" has been caught along with "can't know what files to delete" |
I was hit by the same argparse issue. I guess the |
The argparse issue seems like a legit bug in that it shouldn't be getting caught by this error yea? |
@dstufft, is it not possible to add a CLI argument called |
@daviddyball Yes, and that's a possibility for what we'll do here. Today I'll be poking at the issue and we'll ultimately end up with a decision of some kind for how we proceed. |
We hit the exact same issue as @ianw, only with requests instead of argparse. Isn't the issue here pip trying to uninstall a non-local package? Even if that had all the necessary metadata pip would never be able to do that, so the only sensible thing it can do is suck it up and not error out. |
@wichert is requests already installed by the distro when you try to install requests again? |
Because our requirements.txt pins a specific version so we have the same version everywhere. |
Also, folks should file issues with the relevant projects to unconditionally use setuptools in their |
But if pip can't uninstall the old version, when it does the install it could create a corrupt installation. Is it really any better to ignore the error and (potentially) leave the user with an unusable package? IMO, there isn't really any good answer here. As far as I can see, this only affects people with packages installed that were not installed using pip. I guess that mostly, these are distro-installed packages, and as such, shouldn't people be using their distro package manager to update these, rather than pip? |
The chances of being able to use the distro package manager to get a version of pip, virtualenv, requests, Pillow, etc. to anything more recent than 2 years old is effectively zero. The target audience here are people using something like a Debian or Ubuntu LTS release: they will contain software that is a few years old, and will only receive patches for security fixes. Now your next question is probably going to be: why don't use use a virtualenv that does not expose system packages? The answer to that is: because there are packages that are not installable by pip. For example Python modules for complex C++ libraries that can't use setuptools for compilation (our situation), or because compilation requires more memory then a machine might have available (happens very often with numpy/scipy on VMs). |
Specifically, it's packages installed that were installed using distutils rather than setuptools. Which means all of the following were true:
My estimation is that the vast bulk of these are going to be OS packages where either downstream unconditionally uses distutils, or supports both setuptools and distutils and the OS packager chose to use distutils over setuptools. |
OK, so those scenarios are not ones I'm likely to be affected by, so I don't really have a way of evaluating the options. Are they that common (given that many people will just use a virtualenv)? And are none of the following viable approaches?
I'm basically -1 on letting pip do an install that we know is risky, without the user being told about the risks and consequences. It'd be too easy for us to end up dealing with "pip broke my system" tickets. Presumably people have been seeing the warning about this since it was introduced early last year? And presumably the behaviour was deprecated because it had caused issues prior to that? |
As I explained we do use a virtualenv, so using virtualenv is not a possible solution :) The user can't manually delete the offending package, since that would require root access, and is likely to break the OS. At least as far as we are concerned we just want pip to not try to uninstall something that is not local to the virtualenv. I don't particular mind if that is controlled by a flag, although from a user perspective I probably prefer that pip gives a very clear warning but defaults to skipping the uninstall attempt. |
I'm clearly missing something here. My apologies. You're using a virtualenv. OK. Presumably with use_system_site_packages, as otherwise how come pip's seeing the system package? These are packages that can't be installed with pip, I think you said? If so, why is pip trying to install (upgrade) them? If the user's asking pip to install something that you've confirmed can't be installed with pip, then not being able to uninstall the old version is surely the least of your worries? |
@pfmoore We have packages that can't be installed using pip, but those are not the ones pip is trying to upgrade. We use a virtualenv with system site packages so we can use packages that can not be installed using pip. That also pulls in a set of other packages that are installed by the OS such as requests, pillow and psycopg2. As far as we are concerted that is a side-effect if virtualenv had an option to only selectively expose system packages we would use that to exclude those. We also use exact version pins for all packages in requirements.txt to guarantee that we use the exact same version of all dependencies everywhere. That will include packages that are provided by the OS on some machines for various reasons – for example Ubuntu ships with a bunch of Python packages installed that OSX/MacPorts does not install. When we point pip to that requirements.txt it can try to upgrade packages installed by the OS. That has always worked, but results in a fatal error with pip 8. I suspect the easiest way to reproduce this is to grab an Ubuntu 14.04 LTS box and do this:
This works fine with pip 7. On pip 8 it will abort with an error. |
Ah, OK I see now. Sorry for taking so long to understand. Agreed that the "real" solution would be for virtualenv to have an "expose only the following system packages" option. Maybe what we should do is downgrade the error to a warning if pip is planning to install the new version to a different location than the detected one. (We can't ignore it totally as (a) we don't know which one will take precedence, and (b) there's still the risk of partial shadowing). Installing a package like this, shadowing another installation, would still be an unsupported arrangement, but at least people who understand the risks and want to (or have to) take them, can do so. |
I think @wichert is hitting something different than the underlying issue here, it just so happened that promoting this to an error exposed it. Right now our uninstallation path looks like:
This should be easy to support by splitting the third step up so that the first thing we do is check if the item we're attempting to install is "local" to any currently running virtual environments and simply skipping out earlier than we are currently. The goal here was to fix a slightly different problem, where you're not shadowing via sys.path, but you're literally overwriting files to the same disk location, or you're removing the .egg-info but leaving the package otherwise installed. Those cases don't happen in the specific one that @wichert is having. |
Agreed. What we do in step 3a doesn't care if the existing install is broken, so we can (actual technical details permitting!) do that up front. |
Argparse is another thing that people are running into this issue on, because argparse in the standard library includes a .egg-info file. However the standard library argparse is always going to shadow any installed argparse (because of What do we think about making installing argparse a no-op on 2.7+, 3.3+ and just hard failing if someone attempts to "install" a version specifier of it that doesn't include what is shipped in the standard library? |
Checking in, standard Ubuntu 14.04 image includes gross versions of both requests and six, so attempting to install either system-wide will fail. |
See pypa/pip#3384 Signed-off-by: Zack Cerza <zack@redhat.com>
This should be fixed now in develop. |
Project: openstack/diskimage-builder d79ecfd07664bdcb56711d84fbc691b95d39d961 Use pip 7 for ironic pip8 cannot install the ironic requirements due to pypa/pip#3384. Change-Id: Ic0c70baca83b91cb55ddf4f787c4ff25aaefc062
pip8 cannot install the ironic requirements due to pypa/pip#3384. Change-Id: Ic0c70baca83b91cb55ddf4f787c4ff25aaefc062
See pypa/pip#3384 Signed-off-by: Zack Cerza <zack@redhat.com>
Project: openstack/tempest e9e9cfc5f2b6a3acc30d831151659b0b164503a0 Cap Pip<8 due to pip bug Due to pypa/pip#3384 in pip v8, this change puts a cap on pip, in a similar manner to https://review.openstack.org/#/c/269954/ Change-Id: I20b8b597e8806a7ee21d947eccc98e4ae7e00c3b Closes-Bug: 1536290
Due to pypa/pip#3384 in pip v8, this change puts a cap on pip, in a similar manner to https://review.openstack.org/#/c/269954/ Change-Id: I20b8b597e8806a7ee21d947eccc98e4ae7e00c3b Closes-Bug: 1536290
The pip issue pypa/pip#3384 is already been fixed after pip 8.0.1 released. Since the pip 8.0 version breaks things, just skip it in version pinning. TrivialFix Change-Id: Ida3e7cac5ecfd2ee7266e53650bf1732d5f9d6a0
The pip issue pypa/pip#3384 is already been fixed after pip 8.0.1 released. TrivialFix Change-Id: Ib5bdff63a46ade8da31ddf4516affad6cf1a8029
Project: openstack-dev/devstack 428c35bade09ea814d8ce119498d3beb947f2ee2 Remove the pip version pinning to < 8 The pip issue pypa/pip#3384 has already been fixed after pip 8.0.1 released. But leave the facility to easy flip this on in the future. TrivialFix Change-Id: I49658ce4056c773943321270defd461bbf3e9fb9
Project: openstack-dev/devstack 428c35bade09ea814d8ce119498d3beb947f2ee2 Remove the pip version pinning to < 8 The pip issue pypa/pip#3384 has already been fixed after pip 8.0.1 released. But leave the facility to easy flip this on in the future. TrivialFix Change-Id: I49658ce4056c773943321270defd461bbf3e9fb9
The pip issue pypa/pip#3384 has already been fixed after pip 8.0.1 released. But leave the facility to easy flip this on in the future. TrivialFix Change-Id: I49658ce4056c773943321270defd461bbf3e9fb9
Now that pypa/pip#3384 has been resolved we can use the latest version.
Let's install a specific version of pip instead of latest until pypa/pip#3384 gets addressed
Now that pypa/pip#3384 has been resolved we can use the latest version.
Now that pypa/pip#3384 has been resolved we can use the latest version.
However distributions still ship a bunch of distutils projects - e.g. six, urllib3, jsonpointer, chardet, libvirt-python, pyOpenSSL, PyYAML, netaddr
So this is likely to affect many users.
A variation of this, where a virtualenv is being used also occurs - this shouldn't have been warning ever, since the virtualenv means we won't uninstall, we'll just shadow it. See #3404 for the bug for that.
We could:
The text was updated successfully, but these errors were encountered: