Why you should use pyenv + Pipenv for your Python projects
By: Daniel Van Flymen
Tags: Pip, Pyenv, Python Development, Python, Pipenv

What is Pipenv and how does it work?

Pipenv is the officially recommended way of managing project dependencies. Instead of having a requirements.txt file in your project, and managing virtualenvs, you'll now have a Pipfile in your project that does all this stuff automatically.

Start off by installing it via pip , it’s a rapidly evolving project so make sure you have the latest version (2018.10.13 at the time of writing):

$ pip install -U pipenv

Using Pipenv for the first time

Let’s set up Pipenv in your project:

$ cd my_project

$ pipenv install Creating a virtualenv for this project… Pipfile: /Users/dvf/my_project/Pipfile Using /Users/dvf/.pyenv/versions/3.7.0/bin/python3.7 (3.7.0) to create virtualenv…

You’ll find two new files in your project: Pipfile and Pipfile.lock .

If you’re installing in a pre-existing project, Pipenv will convert your old requirements.txt into a Pipfile . How cool is that?

This is what your Pipfile should look like for a fresh project:

[[source]]

url = "https://pypi.org/simple"

verify_ssl = true

name = "pypi" [packages] [dev-packages] [requires]

python_version = "3.7"

Notice that we didn’t activate any virtual environments here, Pipenv takes care of virtual environments for us. So, installing new dependencies is simple:

$ pipenv install django Installing django

... Installing collected packages: pytz, django

Successfully installed django-2.1.2 pytz-2018.5 Adding django to Pipfile's [packages]…

Pipfile.lock (4f9dd2) out of date, updating to (a65489)…

Locking [dev-packages] dependencies…

Locking [packages] dependencies…

Updated Pipfile.lock (4f9dd2)! Installing dependencies from Pipfile.lock (4f9dd2)… 🐍 ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 2/2 — 00:00:01 To activate this project's virtualenv, run pipenv shell.

Alternatively, run a command inside the virtualenv with pipenv run.

If you inspect your Pipfile you’ll notice it now contains django = "*" as a dependency.

If we wanted to install dev dependencies for use during development, for example YAPF, you’d add --dev to the install step:

$ pipenv install --dev yapf

What is Pipfile.lock ?

Pipfile.lock is super important because it does two things:

Provides good security by keeping a hash of each package installed. Pins the versions of all dependencies and sub-dependencies, giving you replicable environments.

Let’s see what it currently looks like:

Notice that the versions of each dependency are pinned. Without a very good reason, you would always want this file committed to your source control.

Custom Indexes

Until Pipenv it was difficult to use private Python repositories, for example if you’d like to host private Python libraries within your organization. Now all you need to do is define them as an additional sources in the Pipfile :

[[source]]

url = "https://pypi.org/simple"

verify_ssl = true

name = "pypi"



[[source]]

url = "https://www.example.com"

verify_ssl = true

name = "some-repo-name"



[packages]

django = "*"

my-private-app = {version="*", index="some-repo-name"}



[dev-packages]



[requires]

python_version = "3.7"

Notice that we told my-private-app to use the private repo. If omitted, Pipenv will cycle through indexes until it finds the package.

💡Pipenv will also consume any environment variables in values, which is useful if you have sensitive credentials you don’t want sitting in source control (this was my contribution </humblebrag> )

Deploying

When deploying it’s important that your deploy fails if there’s a mismatch between installed dependencies and the Pipfile.lock . So you should append --deploy to your install step which does just that:

$ pipenv install --deploy

You could also check which dependencies are mismatched:

$ pipenv check

And see which sub-dependencies are installed by packages:

$ pipenv graph --reverse pip==18.1

pytz==2018.5

- Django==2.1.2 [requires: pytz]

setuptools==40.4.3

wheel==0.32.2

yapf==0.24.0

Once-off commands, scripts and activating venvs

If you’re actively developing a project, it’s helpful to activate the virtual environment:

$ pipenv shell Launching subshell in virtual environment…

(my_project) ➜ my_project

Or, if you’d like to execute a command inside the venv:

$ pipenv run python manage.py runserver

You can also add scripts to Pipfile similar to npm package.json :



url = "

verify_ssl = true

name = "pypi" [[source]]url = " https://pypi.org/simple verify_ssl = truename = "pypi" [packages]

django = "*" [dev-packages]

yapf = "*" [scripts]

server = "python manage.py runserver" [requires]

python_version = "3.7"

Now you can execute the script:

$ pipenv run server

We’ve just touched the tip of the iceberg. If you’ve like to learn more about Pipenv, I encourage you to read the great documentation.