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-pep517fixes 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.pathfor the subprocess that runs the build backend, but they are put later insys.paththan an older version ofsetuptools. There’s a.pthfile in the latestsetuptoolsthat tries to do some magic, and the magic that it does is busted because the version ofsetuptoolsthat’s earlier on the module search path is an earlier version, incompatible with the.pthfile.A simpler reproducer of this than what I see above is:
which fails with:
This failure is happening because there are two versions of
setuptoolson the search path, an older one (from thesite-packagesdirectory 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.pthfile that tries to importsetuptools._distutils. The.pthfile runs even though another version ofsetuptoolsis 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-pipinstallspython.exe,pythonw.exe,pyvenv.cfgand 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-pipis 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-packagesInside we havepip == 19.2.1We are using pyproject.toml, requirements.txt and setup.cfg and install the latestsetuptools == 63.2.0using thepyproject.tomlWe have the following code in the setup.cfg:
Now we hit the error where the
get_requires_for_build_wheelfails 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.pyFor those struggling with same bug using pip and venv on Debian distros, the current workaround we are using is to either uninstall the
python3-setuptoolsor try to use the--no-build-isolationflag with pipI think the cause is clear. pip implements build isolation by removing the current platlib and purelib directories (and any directories from
.pthfiles in those directories) fromsys.pathusing the code here. Therefore, if there are any system site directories that are not covered by that, they remain insys.pathin 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.pathand not just platlib/purelib.@pganssle it looks like it’s time to remove
--system-site-packagesfrom the title. I’ve already hit two instances of the bug with--no-site-packages.FTR I’m hitting this with
tox+system-site-packageswithsetuptools>=40.8.0inpyproject.tomlunder 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.tomland then just playing with--no-build-isolationI’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
pipandsetuptoolswere installed withpip, when using latestcryptographyfrom PyPI. Note that there’s no other Python 3 installation on the system (and hence no othersetuptoolseither).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-isolationis specified? An isolated build ignores the existing installation.Well, the point of
--no-build-isolationis 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-isolationis 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
pipcreates a customsitecustomize.pyfile 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.BuildEnvironmentdoesn’t have this problem - maybe switch over to using that? Or was there a reason to do it this way?