Using Pipenv
Saturday June 29, 2019
If you use Python, you should use Pipenv for environment/requirement management.
Installing
Do you have Pipenv installed? (Try which pipenv
.) If you don't have
it, install it:
$ pip install --user pipenv
Now you can read pipenv --help
, but I'll continue to highlight
common tasks.
Existing project
Is there an existing Pipfile
? To get things installed, run this in
the project directory:
$ pipenv sync
New project
Starting a new project? There's no explicit "new" command, but you can do this:
$ pipenv --python 3.7
You can also skip that and just start installing things.
Keep Pipfile
and Pipfile.lock
in version control.
Installing your requirements
Just use pipenv
instead of pip
(or other alternatives).
$ pipenv install some_cool_python_package
Pipfile
and Pipfile.lock
will be kept up to date automatically.
Development requirements
Pipenv keeps dev packages (like Pylint, for
example) separate. Just use the --dev
flag:
$ pipenv install --dev some_cool_python_package
$ pipenv sync --dev # install base AND dev packages
Running things
Just use pipenv run
a lot.
pipenv run python whatever.py --etc
That's it!
Pipenv does a lot for you, while requiring very little from you.
I do have more thoughts though...
Why is it good?
Without Pipenv, maybe you track big-picture requirements in
setup.py
's install_requires
, and/or elsewhere. Maybe you have a
requirements.txt
so you have known-good exact versions of
everything. Maybe another such file for dev requirements. And you
probably have to remember to take separate actions to keep these all
up to date and in sync. The pain! The mistakes!
Working directory
I don't generally love magic based on my current working directory,
but Pipenv has won me over. I appreciate that it's explicit, at least.
No environment variables get automatically changed when you change
directories, for example. You have to run some pipenv
command to do
anything with the environment corresponding to where you are on disk.
History
I used to advocate for Pew, so I was interested to see that Pipenv is a kind of descendant of Pew. Pipenv's implementation used to rely on Pew, even.
You can get a shell in your project environment with pipenv shell
and it seems to work more like pew workon
than source activate
.
Perhaps the major workflow difference is that now pipenv run
(like
pew in
) is commonly used, to the exclusion of changing your shell. I
think this is a good thing in that it's more explicit and removes the
risk of forgetting what the current state of your shell is.
Where's my venv, though?
Unless you mess with defaults, virtual environments are stored,
consistent with PEP 370,
in ~/.local/share/virtualenvs/
. They're associated with a Pipfile
via a hash of its path.
Here's a simplified version of the hashing:
import hashlib, base64
def short_hash(path_to_pipfile):
hash = hashlib.sha256(path_to_pipfile.encode()).digest()[:6]
return base64.urlsafe_b64encode(hash)
So the venv for /home/me/project/Pipfile
will be called
project-fPIxLfK7
. You can always check your project with pipenv
--venv
.
This does mean that if you move or otherwise rename your project
directory, Pipenv can lose track of your virtualenv — but it's super
easy to just run pipenv sync
and you're ready to go again.