Pipenv is a tool for managing your Python project’s dependencies, which aims to solve one of the problems with requirements.txt
files. This post will get you started using Pipenv for dependency management, as well as show you how to use Pyenv to work with multiple versions of Python.
Pipenv
Installing dependencies
First, make sure you have Pipenv installed by following the instructions.
Now let’s build a simple Hello World API using Flask.
pipenv install flask
This will create our virtual environment, and install Flask as a dependency. You won’t see a venv
directory - Pipenv stores each virtual environment outside the project folder, and uses the correct one automatically.
You will see a couple of new files in your directory - Pipfile
and Pipefile.lock
. We’ll take a look at them shortly.
Because we’re responsible developers, we’re also going to write a test for our API, so let’s install pytest
. Since we won’t be deploying our tests to production, we can use --dev
to install pytest
as a dev dependency.
pipenv install --dev pytest
Pipfile and Pipfile.lock
Let’s take a closer look at our Pipfile
.
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
flask = "*"
[dev-packages]
pytest = "*"
[requires]
python_version = "3.8"
Much like NPM’s package.json
, it keeps track of our dependencies, dev dependencies, and required language version. Pipfile.lock
will keep track of the exact versions installed. If we commit both these files to version control, then another developer can download our repo, and run:
pipenv install --dev
This will give them exactly the same versions of each dependency.
Creating our app
We’ll create our app in main.py
:
from flask import Flask
app = Flask(__name__)
@app.route("/hello/<name>")
def hello_world(name):
return {"message": f"Hello, {name.title()}!"}
and our test in test_main.py
:
from main import app
def test_hello_world():
with app.test_client() as client:
response = client.get("/hello/your%20name")
assert response.status_code == 200
assert response.json == {"message": "Hello, Your Name!"}
Running our code
To run code using Pipenv, we don’t need to activate a virtual environment - we can just pass our command to pipenv run
. So to run the tests, we’d use:
pipenv run pytest
and Pipenv will run the code in the correct environment. Similarly, to run our new API we’d use:
FLASK_APP=main pipenv run flask run
You should now be able to see the API in action using:
curl http://localhost:5000/hello/your%20name
Pyenv
Installing multiple Python versions
Pyenv lets you install and easily work with different versions of Python on your machine, and it works with Pipenv.
Start by installing Pyenv following the instructions - there’s a little more setup involved than when installing Pipenv, make sure not to miss the pyenv init
step!
Pipenv works by adding a shim to your PATH
, so that whenever you run e.g. python
, it will actually run the shim, which will then decide which Python executable to run.
Let’s try it out by installing Python 3.9:
pyenv install 3.9.0
We can then tell Pyenv to use a specific Python version for code within the current directory. This is great if you work on multiple projects, or just want to try out the latest version of Python.
pyenv local 3.9.0
This will create a .python-version
file in the current directory, which Pyenv will check next time you run code from that directory.
Using Pipenv with Pyenv
Finally, let’s tell Pipenv to use this new version of Python. Remove the existing virtual environment, and recreate it, specifying the Python version we want to use:
pipenv --rm
pipenv install --dev --python=$(pyenv which python)
Your code should now be running with the latest version of Python!