I want to make a small script that automates running something that needs python2 with pipenv.
I would do:
pipenv install --two
pipenv run hello.py
The first invocation is fine, the second time I run this script however it says:
Virtualenv already exists!
Removing existing virtualenv...
Creating a virtualenv for this project...
even though nothing has changed. It's the --two option that causes this. If I remove that option it behaves as I would expect and reuses the old virtualenv, however then I get python3.
Since python3 is the default you don't need --two/--three, so then you don't have this problem.
Hey @ernstp, there seems to be confusion about pipenv
commands here. Both --two
and --three
are destructive options which will completely delete a virtualenv and reprovision with the appropriate python version. I would suggest not using either with install
unless you have a very specific reason for doing so.
You should only need to build your project environment once, so I'd suggest using pipenv --two
as a one-time setup action. After that, you can freely use pipenv install
and pipenv run
which will use the native version of Python in the virtualenv (in this case Python2).
A slightly more robust script that checks if the environment already exists would be something like:
pipenv --venv # Check if virtualenv exists
NO_VENV=$? # Store returned status code in var
if [ $NO_VENV -eq 1 ]; then
pipenv --two
fi
pipenv install
pipenv run hello.py
Hopefully that helps! Thanks for taking the time to open this issue and please let me know if you have any further questions.
Well in an automated (Jenkins etc.) and distributed environment with a number of hosts you don't really know if a venv has been created or not. But it's nice to reuse an environment if possible.
Right, that script works. You can even do "pipenv --venv || pipenv --two" or something very compact. :-)
Also, having a setting for "--python" in Pipfile would solve this.
In something like Jenkins, you'd likely want to be creating your environment from scratch on each build. Every project using a Pipfile has it's own virtualenv created for it, that way you're not having to worry about other state on the machine.
We have had some discussion on populating --python
with the ~require_python
~ python_version
parameter in the Pipfile. The discussion can be found #286 but there are some issues with the approach that have delayed implementation.
The same happens when you pass --python x.x.x
as a parameter - pipenv always rebuilds the virtualenv.
This adds unnecessary wait time to pipenv install --python x.x.x
- if the python version already exists and the virtual environment is setup, I don't see the reason to re-create it every time.
@nateprewitt If enforcing a re-build is truly desired, could there be an option similar to rbenv
's --skip-existing
, skipping the re-creation of the virtualenv when it already exists/python version matches?
@sman591 I think you may have a misconception of what the --python flag is doing. This is saying "create me a brand new virtualenv and reinstall everything". It has a giant note in the docs warning about this.
You can pass it with install as a convenience but it does the same thing. It doesn't make sense to not rebuild the virtualenv every time because it can't be two different versions simultaneously. rbenv is much more analogous to pyenv from my understanding.
Right - I understand that you would never want to use two different versions, but what if the existing virtulaenv python version matches the desired python version? If the versions match, I don't see why it needs to be a destructive action and re-create everything from scratch -- the version is already satisfied, so just skip re-installation.
@sman591 so we could put in a safeguard to help users if they accidentally type the longer command. We're technically circumventing what the command has always done and is documented to do though.
Options are deliberate and if someone passes it, we should do what they're asking to do. Which has previously been wipe the virtualenv and give me a fresh one. This will likely break existing users workflows.
I guess what I wanted to happen was say pipenv install
on my CI server and have a way to ensure it chooses the correct version of python, if the env didnt exist it might grab the system version first because it finds it on the path first, which is bad, but if a virtualenv already exists with that version, I don't want it to destroy it. With the existing behaviors I am not sure how to make that happen.
The short description on the docs describe it as "Specify which version of Python virtualenv should use." I think this would still conform to that: it ensures the correct version is used. If the virtualenv doesn't exist, or has the wrong version, it installs/overwrites it; if it's the correct version, it continues on like any other pipenv install
would today.
It could also print a notice to the console that the python version matches the requirement, and therefore won't be reinstalled. Something like "Python version x.x.x already satisfied (use pipenv --rm && pipenv install --python x.x.x
to reinstall Python)". However I still don't think people really expect pipenv install --python
to re-create the virtualenv.
Fwiw, it originally surprised me that the Python version was controlled/installed via a flag (--two
or --python
), rather than its own command (eg pipenv python x.x.x
)
Pipenv is supposed to manage virtualenvs for you, so when it removes one it shouldn't really be a big deal. As for CI workflow, set the environment variable PIPENV_DEFAULT_PYTHON_VERSION
.
well, pipenv doesn't do this right now, not sure if its a future plan or possible, but my hope is that one day you pipenv install
and it works like yarn
which doesnt even go out to the internet and can verify that all local dependencies are installed in a few seconds. If this happens with pipenv
in the future, destroying the virtual environment will make this not work.
I will try the PIPENV_DEFAULT_PYTHON_VERSION
, thanks! I guess it should also respect what is listed in the Pipfile
?
Yes if you don鈥檛 specify a version in the pipfile or with pipenv install
it will check the environment variable. If the Pipfile has a required python version it will prefer that. BTW, pipenv install
alone won鈥檛 wipe an environment, that only happens in the case when you also specify an interpreter. That tells pipenv to rebuild with the indicated interpreter.
I'd like to second the intuition that even explicit arguments won't repeat work unnecessarily.
Most helpful comment
I'd like to second the intuition that even explicit arguments won't repeat work unnecessarily.