pip: virtualenv with --system-site-packages breaks pip's build isolation
It seems that if you create a virtualenv with --system-site-packages
, the system packages (but not the user packages) will be on the PYTHONPATH
in the PEP 517 isolated build environment that pip
creates (it does not effect python -m pep517.build
), and it seems they will be on there with higher precedence than the requirements installed in the build environment. It only affects pip >= 19.0.0
.
The most common way I’ve seen this cause problems is with the new setuptools.build_meta:__legacy__
backend. Since the most recent version of pip
requires a recent version of setuptools
, if you have an older version of setuptools
installed on the system, pip install
will fail due to the missing setuptools.build_meta:__legacy__
backend. It is possible to reproduce this by crafting a deliberately bad package and installing it, then creating a wheel for a newer version of the package (which allowed me to test that this failure was actually introduced with pip==19.0.0
), but for the MWE we can stick with setuptools
.
To reproduce, create a package like this:
cd /tmp
mkdir demo
cd demo
mkdir badpkg
touch badpkg/pyproject.toml
echo 'from setuptools import setup; setup(name="foo", version="0.1.0")' \
> badpkg/setup.py
Then install an older version of setuptools
on your system (can’t be --user
or in the virtualenv), pip install 'setuptools < 40.8.0'
(I did this in a pyenv
environment). If your system already has an older version of setuptools
on it, you’re already good.
Next create a virtualenv with --system-site-packages
and activate it:
virtualenv venv --system-site-packages
source venv/bin/activate
Finally try to install badpkg
(pip wheel
or pip install -t tmp
also works to demonstrate the problem):
pip install ./badpkg
You should get a traceback the ends like this:
AttributeError: module 'setuptools.build_meta' has no attribute '__legacy__'
At first I thought this was because the affected packages had too loose bounds on build-system.requires
(e.g. requires=["setuptools"]
) and that pip
was failing to install a more recent version in the isolated environment, but this bug still occurs even if you specify "setuptools>=40.8.0"
, so I believe it’s not a problem at install-time, it’s a problem with the path resolution at build time.
At the moment it’s unclear if this is a problem with pip
or virtualenv
, but since it does not affect python -m pep517.build
, I’m reporting it here. It could be a combination of both.
CC: @gaborbernat
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 31
- Comments: 82 (49 by maintainers)
Commits related to this issue
- Upgrade setuptools on Python from system The issue related to pypa/pip is happening because pip somehow fails to properly isolate build env in PEP 517 mode. Related to https://github.com/rtfd/readth... — committed to readthedocs/readthedocs-docker-images by humitos 5 years ago
- 📝 Add a link to the pip bug Ref: pypa/pip#6264 — committed to webknjaz/molecule by webknjaz 5 years ago
- Update the installation assumptions doc (#1968) * 📝 Document having user-level setuptools updated * 📝 Bump versions in the Test PyPI demo * 📝 Update the recommendations about bleeding-edge ... — committed to ansible/molecule by webknjaz 5 years ago
- Resolving orc8r egg link python install bug Summary: There's a bug for virtualenv installations using pip when pip version is `>=19.0.0` AND setuptools system package version is less than `40.8.0` (s... — committed to magma/magma by ardzoht 5 years ago
- Update setuptools too to try and avoid pypa/pip#6264 — committed to chriseclectic/qiskit-ignis by mtreinish 5 years ago
- Change default solver to CVXPY default for CVX tomography (#300) * Remove cvxopt from requirements, update docs * add blas+lapack to travis * ignore built docs * install cvxpy through conda ... — committed to qiskit-community/qiskit-ignis by chriseclectic 5 years ago
- Resolving orc8r egg link python install bug Summary: There's a bug for virtualenv installations using pip when pip version is `>=19.0.0` AND setuptools system package version is less than `40.8.0` (s... — committed to gjalves/magma by ardzoht 5 years ago
- Travis: Run py36 unit tests on CentOS 8 CI image Change Travis to use CentOS 8 for unit test on python 3.6 instead of Fedora. Due to pip/setuptools bug: https://github.com/pypa/pip/issues/6264 , upg... — committed to cathay4t/nmstate by cathay4t 4 years ago
- Travis: Run py36 unit test on CentOS 8 CI image Change Travis to use CentOS 8 for unit test on python 3.6 instead of Fedora. Due to pip/setuptools bug: https://github.com/pypa/pip/issues/6264 , upgr... — committed to cathay4t/nmstate by cathay4t 4 years ago
- Travis: Run py36 unit test on CentOS 8 CI image Change Travis to use CentOS 8 for unit test on python 3.6 instead of Fedora. Due to pip/setuptools bug: https://github.com/pypa/pip/issues/6264 , upgr... — committed to cathay4t/nmstate by cathay4t 4 years ago
- Travis: Run py36 unit test on CentOS 8 CI image Change Travis to use CentOS 8 for unit test on python 3.6 instead of Fedora. Due to pip/setuptools bug: https://github.com/pypa/pip/issues/6264 , upgr... — committed to nmstate/nmstate by cathay4t 4 years ago
- Fix for PEP517 issue with Python 3.6.8 When creating a virtualenv with Python 3.6.8 using the --system-site-packages option and pip>=19.0.0 a bug affects the virtualenv breaking pep build isolation. ... — committed to openstack/bifrost by elfosardo 4 years ago
- Update git submodules * Update bifrost from branch 'master' - Fix for PEP517 issue with Python 3.6.8 When creating a virtualenv with Python 3.6.8 using the --system-site-packages optio... — committed to openstack/openstack by elfosardo 4 years ago
- Fix CI jobs Cinder added a new restriction to the snapshots in the DB in change I47ff8115ae74e1a7ad41869159871ba614c388ac and now snapshot's volume_type_id cannot be null. This broke the cinderlib C... — committed to openstack/cinderlib by Akrog 4 years ago
- Update git submodules * Update cinderlib from branch 'master' - Fix CI jobs Cinder added a new restriction to the snapshots in the DB in change I47ff8115ae74e1a7ad41869159871ba614c388a... — committed to openstack/openstack by Akrog 4 years ago
- explicit build-backend workaround pip build isolation bug 6264 pip issue https://github.com/pypa/pip/issues/6264 workaround https://github.com/pypa/setuptools/issues/1694#issuecomment-466010982 fixe... — committed to httplib2/httplib2 by temoto 4 years ago
- explicit build-backend workaround pip build isolation bug 6264 pip issue https://github.com/pypa/pip/issues/6264 workaround https://github.com/pypa/setuptools/issues/1694#issuecomment-466010982 fixe... — committed to httplib2/httplib2 by temoto 4 years ago
- fix(build): explicit build-backend workaround pip issue pypa/pip#6264 workaround https://github.com/pypa/setuptools/issues/1694#issuecomment-466010982 see also https://github.com/httplib2/httplib2/co... — committed to freelawproject/judge-pics by mlissner 4 years ago
- Test PIP_NO_BUILD_ISOLATION (#8255) Fixes #8252 With @bmw we digged quite a lot on why the failure happens on ARM snap, and here we what we understood: * the failure occurs since the version 50 o... — committed to certbot/certbot by adferrand 4 years ago
- Resolve pypa/setuptools#2353 and pypa/pip#6264. This commit resolves recent catastrophic upstream breakage introduced by setuptools 50.0 and pip 22.2.0, the newest stable release of everyone's least ... — committed to beartype/beartype by leycec 4 years ago
I should also mention that
--no-use-pep517
fixes the problem for me.I believe this is the root cause of #8823 and https://github.com/pypa/setuptools/issues/2353 - a PEP 517 build of a package is performed, its build requirements are installed into a directory that is added to
sys.path
for the subprocess that runs the build backend, but they are put later insys.path
than an older version ofsetuptools
. There’s a.pth
file in the latestsetuptools
that tries to do some magic, and the magic that it does is busted because the version ofsetuptools
that’s earlier on the module search path is an earlier version, incompatible with the.pth
file.A simpler reproducer of this than what I see above is:
which fails with:
This failure is happening because there are two versions of
setuptools
on the search path, an older one (from thesite-packages
directory of the interpreter that created the virtualenv) and a newer one (installed as part of the build requirements for the PEP 517 build). The newer one is shipped along with a.pth
file that tries to importsetuptools._distutils
. The.pth
file runs even though another version ofsetuptools
is before it in the module search path, but the import it performs fails because the old version, earlier on the search path, doesn’t containsetuptools._distutils
.That’s exactly my plan 😛 pip already uses pep517 under the hood, and the main reason it does not also use its isolated environment implementation is because pep517 maintainers don’t want anything outside of the core PEP 517 interface to be depended on. It would be best IMO if the isolated environment implementation is maintained outside of pip (so other projects can reuse it), and python-build would be in the perfect position since it does the exactly thing pip needs, and already plans to join PyPA.
venv --without-pip
installspython.exe
,pythonw.exe
,pyvenv.cfg
and 4 activaion scripts on my Windows PC, and takes essentially no time. I think it’s perfectly acceptable. It’s not like the “old days” when creating a virtual environment installed a big chunk of the stdlib.I don’t think it’s that we can’t use virtualenv, but rather (if we’re not installing pip etc) that we don’t need it -
venv --without-pip
is perfectly sufficient, and comes with the stdlib, so there are no vendoring issues.I also hit this problem. In my case, downgrade pip. it works.
@pfmoore if virtualenv inherits the system site package (and that has a setuptoools before 40.8.0) the pip install of the setuptools build dependency is ignored (as pip does not check the version of what is installed unless -U is passed, and says any setuptools satisfies the install requirement); therefore once pip tries to get the build backend the above failure is thrown. I don’t think there needs to be anything wrong with system python to fall into this issue. pip should make sure to never-ever create an isolated build environment that inherits from the system site package, which is not the case at the moment.
Inside a Debian GNU/Linux 10 (buster) Docker container we create a virtual-env with
--system-site-packages
Inside we havepip == 19.2.1
We are using pyproject.toml, requirements.txt and setup.cfg and install the latestsetuptools == 63.2.0
using thepyproject.toml
We have the following code in the setup.cfg:
Now we hit the error where the
get_requires_for_build_wheel
fails with parsing error of the above setup.cfg.Upon inspection we found out that pip instead of loading the latest setuptools from the build environment loaded the setuptools == 40.8.0 from dist-packages and used the build_meta from
/usr/lib/python3/dist-packages/setuptools/build_meta.py
For those struggling with same bug using pip and venv on Debian distros, the current workaround we are using is to either uninstall the
python3-setuptools
or try to use the--no-build-isolation
flag with pipI think the cause is clear. pip implements build isolation by removing the current platlib and purelib directories (and any directories from
.pth
files in those directories) fromsys.path
using the code here. Therefore, if there are any system site directories that are not covered by that, they remain insys.path
in the build environment.In the case of a virtual environment with
--system-site-packages
, the current platlib/purelib directories are the ones inside the venv, so any system site directories are not removed. I expect this to happen on any distribution.In the case of Debian, the system Python has an extra site directory,
/usr/local/lib/python3.6/dist-packages
, which is neither the platlib nor purelib directory, so it’s not removed.It seems to me that the simplest fix would be to remove all directories in
site.getsitepackages()
fromsys.path
and not just platlib/purelib.@pganssle it looks like it’s time to remove
--system-site-packages
from the title. I’ve already hit two instances of the bug with--no-site-packages
.FTR I’m hitting this with
tox
+system-site-packages
withsetuptools>=40.8.0
inpyproject.toml
under Python 2.7.15. I was actually hitting pypa/setuptools#1136 originally (which I knew was fixed a while back) and only after some time of playing around with removingpyproject.toml
and then just playing with--no-build-isolation
I’ve found this one…Couldn’t figure it out for a while because it was only reproducible in Travis CI which drops you into a virtualenv from the beginning automatically. Had to request debug access to their VMs to nail it down…
@pfmoore Same problem when
pip
andsetuptools
were installed withpip
, when using latestcryptography
from PyPI. Note that there’s no other Python 3 installation on the system (and hence no othersetuptools
either).Works fine when using
--no-use-pep517
:I believe pypa/setuptools#3291 is another kind of this issue. Note that it neither involves virtualenv, nor Debian/Centos, but sympthoms are exactly the same: system-wide older version of setuptools has higher priority than one that is requested by
pypackage.toml
.It’s still worth having the reproducer, when we find out the cause of the main issue here we can check if it addresses the debian case as well.
here’s a hacky patch which fixes the issue by avoiding site in the isolated environment:
this appears to “fix” today’s breakage with setuptools 61
I also hit this problem when installing the DonkeyCar system that uses many python machine learning libraries. I downgraded to pip 19.0 and everything seems to be working fine. Thank you Naisy.
Presumably when
--no-build-isolation
is specified? An isolated build ignores the existing installation.Well, the point of
--no-build-isolation
is that the user is agreeing to set up the correct build environment, so that seems like it’s a simple case of user error.However, in this case @boegel is claiming that he has setuptools 40.8.0 installed, and no other setuptools is present. If that’s the case, and his setuptools doesn’t contain
build_meta.__legacy__
, then that setuptools installation is somehow broken, because 40.8.0 does contain that backend.My suspicion is that @boegel is actually mistaken, and there’s another copy of setuptools lingering around somewhere, which is getting picked up and is confusing things. The other possibility is that there’s a bug somewhere - but if that is the case, then we’re currently struggling to reduce the example to something that can easily reproduce/demonstrate that bug.
Well, yes, that’s sort of the definition of “isolated” 😃 But I’m not sure how relevant that is in this case, where
--no-build-isolation
is set.That’s what @pganssle is saying in the original post in this thread, yes. But I’m responding to @boegel, who is claiming that he can reproduce the problem without a virtualenv, using
--no-build-isolation
.If @boegel’s problem turns out to be real, then I don’t think it’s related to this one (there’s too many differences in the steps to reproduce it). So it should probably be a separate issue. But I’d be interested to understand why he thinks it is the same issue…
Per my Bloomberg colleague @lkollar, it seems that the problem is that
pip
creates a customsitecustomize.py
file in order to inject itself into the build environment.Looks to me like it’s just blacklisting the system packages with
distutils.get_python_lib
, which doesn’t include the system path added byvirtualenv
. Seems likepep517.envbuild.BuildEnvironment
doesn’t have this problem - maybe switch over to using that? Or was there a reason to do it this way?