-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Lock file differs depending on Python version of Pipenv installation #857
Comments
Are you using the latest version? |
Yes:
|
This may be related to #848. The Python 3 installation of pipenv seems to ignore the environment markers in the |
Even if To list and resolve the dependencies, we fetch the wheels of the packages. These wheels can be different, and provide different dependencies, depending on whether we are on Python 2 or Python 3 (ex: To make/compile a "universal" We've hit the same issue with |
Thanks, I understand the perfect solution might be complicated. What surprised me was that Maybe |
From the Readme: |
Closing issue! I think the docs make it clear what |
The issue is not resolved though. The documentation should at the very least state that to create Python 2 compatible |
@mpolden I think that's pretty self explanatory. I'm open to feedback from some other maintainers though! @vphilippon @nateprewitt @techalchemy |
Saw this the other day but wasn’t sure what to say... how could something you installed using python 3 and therefore runs in python 3 then run itself in the python 2 interpreter? I mean, there are conceivably ways but it’s a horrible practice and it doesn’t work very well... why would you want this when you can do a python2 install of pipenv? |
In my case I think didn't think much about it. I use a Python 3 environment in my dev environment, but deploy to a Python 2 environment. There's also the options
which I assumed would provide the needed compatibility. Additionally, the docs seems to nudge the user towards Python 3. From https://docs.pipenv.org/install.html#make-sure-you-ve-got-python-pip:
And finally, deterministic builds seems to be a key selling point in the features list. From https://docs.pipenv.org/#pipenv-features
It was not obvious to me that the results of dependency resolution would depend on the Python version used by pipenv itself (and not the virtualenv) , and I couldn't find any mention of this behavior in the documentation. |
Well, my thought on this is that if I actually thought this was dealt with somehow with a |
Yeah, there's something weird going on here. Which version of Python you install pipenv on should not be affecting the lock file. A venv established with --two vs --three will have differing results and the os can affect the final output, but the system Python version is supposed to be irrelevant. |
So if I'm understanding correctly: If Python3 is the system python and you create a virtualenv using python2 from a pipenv that's installed with py3, the lock file will be different than if pipenv was installed with a system python of 2.7? If so what are the changes between the lock file? |
@erinxocon You're correct. The difference would be that the lockfile would contain Python 3 dependencies instead of Python 2 dependencies. In short: the dependencies would be computed based on the python environment that But, it might be a bit more complex than that. Python version specific dependencies can be determined from various means. It can be with environment markers, or by the py2 and py3 wheels listing different dependencies, or some specific code in the setup.py when dealing with sdists. At this point, I cannot tell if one or all of the above are impacted by the "root python version". The whole "get stuff for the right environnement" is dealt by |
@vphilippon I know he was working on this around the time of this commit: 7d2927f -- might be worth looking around that time, i can dig into this in a little bit |
@vphilippon @erinxocon here is the list of commits I can find with regard to locking / patching pip / python version hacks / dependency resolution: Not sure what to make of all of this but the answer to this issue lies somewhere in all of these commits, I would guess. |
Similar discussion in jazzband/pip-tools#563 (especially this, this and this comment). If it's not possible, or feasible, to support "universal" lock files (which is just ok), it should be at least clearly documented, so user doesn't get false expectations. You simply get the lock file for the python version / OS platform you compiled on (until future improvements may or may be introduced)? (But I assume this is offtopic, as the original issue was about using virtualenv python environment and not pipenv installation environment to calculate the lock file.) |
So I've been thinking about this @vphilippon @techalchemy and @nateprewitt. Is this related to #1014 with the wrong python version being used to create a lock file? |
@erinxocon yes, for sure. It's the same issue. I know @vphilippon is looking at this some when he can, I've spent a few spare minutes on this when I have them but it really requires a deep dive and a lot of focused effort to figure out where the last bit of trickery needs to happen. |
Small update: This is in my mind (days and night 😄 ), and I hope to be able to dive into that, but this won't be a mere 10 minutes task. I have to find the time to dive into this, so sorry for the delay. |
@vphilippon Good to hear you're working on it. Thanks! |
In our workflow, we use macOS for development & docker for deployment to Linux (AWS Lambda or EC2 instances). Our codebase is a mix of Python2 & Python 3 services deployed independently. While investigating Pipenv, I realized that the Pipfile.lock generated on macOS for a python2 project fails to work within docker. I have installed pipenv in python3 in macOS. The culprit is cryptography package which includes ipaddress packed on python < 3. The fix for this issue will provide the solution for this use case. However, lockfile being dependant on the OS is contrary to my expectations set up by npm, go dep, nuget & other tools. If there are no plans to make lockfile independent of OS, this point should be clearly mentioned in the documentation. |
@surajbarkale-dolby lockfiles aren't OS dependent, that metadata is included just for informative purposes |
Restating the core of the problem: we really want the lockfile to always capture and pin a package superset that covers both platform independent dependencies, and potential platform dependent dependencies (those that include environment markers). This would then be more akin to what we do for unpinned dependencies in wheel files and setup.py files: all the dependencies for every platform would always be listed, but exactly which ones would get installed would be based on the listed environment markers. So while "run pipenv with the same Python you're going to deploy with" is OK as an interim workaround (albeit one that limits pipenv's suitability for managing library test suites), I'm thinking a long term solution is going to look more like the following:
There are still ways for such an approach to fail (e.g. platform specific dependencies that don't even support having their dependency metadata extracted on other platforms), but I think it's the closest we're going to be able to get to the objective of having the dependencies listed in the lock file be platform independent. |
@ncoghlan I agree wholeheartedly, and I actually think we can accomplish this. Previously we approached this by forcing the resolver to use a fake However, pip only makes this assumption in one place, and since we are vendoring a patched version of pip, I believe we can just replace the conditional with some exception handling anyway.
Unfortunately this is the one I'm not so sure about. All of the resolver tools in pip depend on ABI flags, so essentially we would have to tell the resolver to resolve against all possible ABI flag combinations, and not even just for the current platform. How far does this go? Do we include different pythons as well? I haven't tested this quite yet, but I have a general sense that this will not be straightforward because of:
In particular I am thinking of Interestingly, PyPI json just began including platform, requires_dist, and requires_python keys but they are not reliably populated. If they do become populated, this may provide one path when dealing with the official repository anyway. |
In the case of |
@uranusjr in some issue or other I recently proposed that, but in a recent discussion with @kennethreitz he reminded me that we did try that without much success. I did however have some success passing information back and forth across a subprocess call to extract ABI tags and such because you can actually pass that information to the base pip resolver (on which pip-tools relies), but it was insufficient for actual resolution because pip-tools creates This has become quite tangled, and on several occasions I have contemplated isolating and reimplementing the resolver functionality in pipenv so that it works the way we want it to, rather than performing all of these quite frankly ugly hacks to attempt to force existing resolvers to cooperate. Now that I've actually put that in writing, I'd be curious to hear your thoughts. /cc @ncoghlan @nateprewitt @erinxocon @vphilippon |
@techalchemy Yeah, I think this is a case where attempting to re-use the existing installation-focused resolvers is actually the root of the current problem, since the requirements for platform-independent lock file resolution are just different enough that we've ended up trying to fit a square peg into a hole with slightly rounded corners. If Python didn't support environment markers I believe the existing approach would work, but as things stand, the platform-dependent nature of dependency installation is leaking out into the lockfile generation. For cases like
And we'd then advise publishers to either 1) make their metadata extraction work cross-platform; or 2) upload wheel files so PyPI can extract and publish the metadata via the JSON API @uranusjr I originally also thought running the lock file generation inside the venv would be enough, but then I later realised it still isn't enough to solve the problem:
|
@techalchemy That said, I think the problem we're facing here might actually be relevant to pip-compile as well, it's just that because pip-tools doesn't try to enforce a 1-to-1 correspondence between input files and lock files, it's easier to work around the issue by generating separate requirements files for different target environments. |
I think @joshfriend's comment at #1255 (comment) highlights another case where the current platform dependence of lock files is problematic: if you destroy the virtual environment and recreate it with a different Python version or a different Python implementation, That's actually the desired behaviour (since the lock file is nominally platform independent, change versions or implementations shouldn't inherently lead to different lock file contents outside the |
Until pypa/pipenv#857 is fixed, pipenv and hypothesis don't quite play will together.
Chatting to @kennethreitz this evening, he's interested in trying the "Resolve dependencies using the virtualenv Python" approach again, and amending Implicitly setting While I think this would be an improvement over the status quo for the primary deployment use case, I think it may prove problematic for the test suite management use case: https://docs.pipenv.org/advanced/#testing-projects |
As of v11, managing Py2 environments with Py3 (and vice-versa) should be markedly improved, as ecf7842 means the dependency resolution for lock file generation now runs in the context of the venv Python. In particular, if a |
Pipenv seems to create a different lock file depending on whether Pipenv was installed with
pip2
orpip3
.Example with pipenv installed using
pip2 install --user pipenv
:And pipenv installed with
pip3 install --user pipenv
:Using
pipenv --two update
in the last example gives the same result.This effectively means that it's not possible to use a Python 3 Pipenv to generate a
Pipfile.lock
orrequirements.txt
that is usable in a Python 2 environment.The text was updated successfully, but these errors were encountered: