How to use pipenv in your python project

How to use pipenv in your python project

“goodbye requirements.txt, hello Pipfile”

In this article, I will introduce you to pipenv and show you how easy it is to use. pipenv removes the awkwardness of working with virtual environments and module dependencies. Once you spend 15 minutes with pipenv, you will realize the clarity and time savings it will bring to your python project.

DigitalOcean offers one-click deployment of popular applications such as WordPress, Django, MongoDB, Docker, and even preconfigured Kubernetes Clusters. Deploy your next app in seconds. Get $100 in cloud credits from DigitalOcean

Ad Notice I will receive a small commission that helps support this blog at no cost to you.

Read Python for Data Analysis from O’REILLY on Safari with a 10-day trial.

What is pipenv?

pipenv was created by Kenneth Writze, the author of the extremely popular Requests package for python.  In his own words…

Pipenv is a dependency manager for Python projects. If you’re familiar with Node.js’ npm or Ruby’s bundler, it is similar in spirit to those tools. While pip can install Python packages, Pipenv is recommended as it’s a higher-level tool that simplifies dependency management for common use cases. – The Hitchhiker’s Guide to Python

The Python Software Foundation says pipenv and Pipfile are the recommended (if not Official) dependency management tools for python.

How pipenv works

  • pipenv keeps all virtual environment files in ~/.virtualenvs
  • pipenv keeps track of module dependencies in Pipfile (stored in the root of your project)
  • pipenv’s Pipfile replaces requirements.txt
  • pipenv keeps track of what’s been installed in the file Pipfile.lock

 

Here is an example Pipfile from one of my projects

[[source]]

url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"


[packages]

flask = "*"
flask-pymongo = "*"
jsonify = "*"
flask-restful = "*"
requests = "*"
flask-limiter = "*"


[dev-packages]



[requires]

python_version = "3.6"

How to install pipenv

pip install pipenv

Note: Depending on how python3 is installed you may need to type pip3 install pipenv

How to use pipenv

Create a new virtual environment

pipenv --python 3.6

user1@host:~/dev$ mkdir myproject
user1@host:~/dev$ cd myproject/
user1@host:~/dev/myproject$ pipenv --python 3.6
Creating a virtualenv for this project…
Using /usr/bin/python3.6m to create virtualenv…
⠋Running virtualenv with interpreter /usr/bin/python3.6m
Using base prefix '/usr'
New python executable in /home/user1/.local/share/virtualenvs/myproject-PQ8tLRDS/bin/python3.6m
Also creating executable in /home/user1/.local/share/virtualenvs/myproject-PQ8tLRDS/bin/python
Installing setuptools, pip, wheel...done.

Virtualenv location: /home/user1/.local/share/virtualenvs/myproject-PQ8tLRDS
Creating a Pipfile for this project…
user1@host:~/dev/myproject$

Activate a virtual environment

pipenv shell

# Activate a virtual environment with pipenv

user1@host:~/dev/myproject$ pipenv shell
Spawning environment shell (/bin/bash). Use 'exit' to leave.
user1@host:~/dev/myproject$ source /home/user1/.local/share/virtualenvs/myproject-1kHtQjc6/bin/activate
(myproject-1kHtQjc6) user1@host:~/dev/myproject$ 

Executing code without activating your virtual environment

pipenv run python app.py

No need to activate your virtual environment each time, just type pipenv run followed by the command you would normally run after activating your venv.


Install a Package

pipenv install requests

pipenv install pandas

Traditionally, you would have to activate your virtualenv and then run pip install requests. Or if you were using a requirements.txt file you would add the desired package to requirements.txt, activate your virualenv, and run pip install -r requirements.txt

Now, with just one command, we add the package to our Pipfile and pipenv installs it immediately. We didn’t have to activate the virtualenv, just run the command from inside our project directory.

Install a specific version of a package

pipenv install Flask=='0.11.*'

This command will install the latest 0.11 version of flask and update the Pipfile to target this version.

[packages]

requests = "*"
pandas = "*"
flask = "==0.11.*"

Development only Packages

pipenv install --dev nose

pipenv install --dev pytest

Your project will likely use some development only packages for testing such as nose, pytest, tox, etc. The -dev flag will place these packages in a seperate [dev-packages] section of your pipfile.

[packages]

requests = "*"
pandas = "*"
flask = "==0.11.*"


[dev-packages]

"nose2" = "*"
pytest = "*"

Uninstall all packages

pipenv uninstall --all

Remove all packages from the virtualenv.

pipenv uninstall --all-dev

Remove all dev packages from the virtualenv.


Migrate from requirements.txt to Pipfile

pipenv install -r requirements.txt

This command will read in an existing requirements.txt file and populate your Pipfile for you. Simple!


Module Dependency Graph

pipenv graph

This will print all of your project’s installed module versions as well as the pip modules they depend on.

user1@host$ pipenv graph
Flask-Limiter==1.0.0
  - Flask [required: >=0.8, installed: 0.12.2]
    - click [required: >=2.0, installed: 6.7]
    - itsdangerous [required: >=0.21, installed: 0.24]
    - Jinja2 [required: >=2.4, installed: 2.10]
      - MarkupSafe [required: >=0.23, installed: 1.0]
    - Werkzeug [required: >=0.7, installed: 0.12.2]
  - limits [required: Any, installed: 1.2.1]
    - six [required: >=1.4.1, installed: 1.11.0]
  - six [required: >=1.4.1, installed: 1.11.0]
Flask-PyMongo==0.5.1
  - Flask [required: >=0.8, installed: 0.12.2]
    - click [required: >=2.0, installed: 6.7]
    - itsdangerous [required: >=0.21, installed: 0.24]
    - Jinja2 [required: >=2.4, installed: 2.10]
      - MarkupSafe [required: >=0.23, installed: 1.0]
    - Werkzeug [required: >=0.7, installed: 0.12.2]
  - PyMongo [required: >=2.5, installed: 3.5.1]
Flask-RESTful==0.3.6
  - aniso8601 [required: >=0.82, installed: 1.3.0]
    - python-dateutil [required: Any, installed: 2.6.1]
      - six [required: >=1.5, installed: 1.11.0]
  - Flask [required: >=0.8, installed: 0.12.2]
    - click [required: >=2.0, installed: 6.7]
    - itsdangerous [required: >=0.21, installed: 0.24]
    - Jinja2 [required: >=2.4, installed: 2.10]
      - MarkupSafe [required: >=0.23, installed: 1.0]
    - Werkzeug [required: >=0.7, installed: 0.12.2]
  - pytz [required: Any, installed: 2017.3]
  - six [required: >=1.3.0, installed: 1.11.0]
jsonify==0.5
requests==2.18.4
  - certifi [required: >=2017.4.17, installed: 2017.11.5]
  - chardet [required: >=3.0.2,<3.1.0, installed: 3.0.4]
  - idna [required: >=2.5,<2.7, installed: 2.6]
  - urllib3 [required: <1.23,>=1.21.1, installed: 1.22]


user1@host$

Update pip packages

After some time has passed we will want to upgrade to the latest versions of our installed pip packages. This is painless with pipenv, just type…

pipenv update

Here is what it looks like when you use pipenv to upgrade all of your pip packages.

user1@host:~/dev/myproject$ pipenv update
Updating all dependencies from Pipfile…
Found 4 installed package(s), purging…
Uninstalling numpy-1.13.3:
  Successfully uninstalled numpy-1.13.3
Uninstalling pandas-0.21.0:
  Successfully uninstalled pandas-0.21.0
Uninstalling python-dateutil-2.6.1:
  Successfully uninstalled python-dateutil-2.6.1
Uninstalling pytz-2017.3:
  Successfully uninstalled pytz-2017.3

Environment now purged and fresh!
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (5de24b)!
Installing dependencies from Pipfile.lock (5de24b)…
     ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 5/5 — 00:00:09
To activate this project's virtualenv, run the following:
 $ pipenv shell
All dependencies are now up-to-date!
user1@host:~/dev/myproject$ 

Keeping your virtualenv inside your project directory

You might feel more comfortable storing your virtualenv inside your project directory. i.e.project/.venv No problem, pipenv supports this if you set the environment variable PIPENV_VENV_IN_PROJECT. Let’s try it.

user1@host:~/dev/myproject$ pipenv --rm                  
Removing virtualenv (/home/user1/dev/myproject/.venv)…
user1@host:~/dev/myproject$ export PIPENV_VENV_IN_PROJECT=1
user1@host:~/dev/myproject$ pipenv install
Creating a virtualenv for this project…
Using /usr/bin/python3.6m to create virtualenv…
⠋Running virtualenv with interpreter /usr/bin/python3.6m
Using base prefix '/usr'
New python executable in /home/user1/dev/myproject/.venv/bin/python3.6m
Also creating executable in /home/user1/dev/myproject/.venv/bin/python
Installing setuptools, pip, wheel...done.

Virtualenv location: /home/user1/dev/myproject/.venv
...
user1@host:~/dev/myproject$ pipenv --venv
/home/user1/dev/myproject/.venv
user1@host:~/dev/myproject$ ls -la
total 32
drwxrwxr-x 3 user1 user1  4096 Jan  6 08:40 .
drwxrwxr-x 3 user1 user1  4096 Jan  6 07:27 ..
-rw-rw-r-- 1 user1 user1   226 Jan  6 08:04 Pipfile
-rw-rw-r-- 1 user1 user1 14400 Jan  6 08:29 Pipfile.lock
drwxrwxr-x 5 user1 user1  4096 Jan  6 08:40 .venv
user1@host:~/dev/myproject$

If you would like to persist this behavior you can add the PIPENV_VENV_IN_PROJECT variable to your .bashrc file.

echo "export PIPENV_VENV_IN_PROJECT=1" >> ~/.bashrc


Amazon AWS too complex and expensive? You will love the simplicity of DigitalOcean. Deploy your next app in seconds. Get $100 in cloud credits from DigitalOcean

Ad Notice I will receive a small commission that helps support this blog at no cost to you.

In Closing

I hope you enjoyed following along with this pipenv tutorial. Maybe it will save you some time and pain on your next python project.

Don’t forget, pipenv is the new way to manage package dependencies for python.
Goodbye requirements.txt, Hello Pipfile

References

More Python Goodness

One Reply to “How to use pipenv in your python project”

  1. I’m loving pipenv, too. A couple of added benefits that you didn’t bring up. Running pipenv run or pipenv shell will automatically inject key-value pairs into your environment if you have a .env file in the same directory as the pipfile (there is a setting to configure that directory, though). Also combining pipenv with a setup.py file is a fantastic way to establish the module dependencies (in setup.py) and the environment (in the pipfile). In the setup() method, you can set the module requirements with install_requires=[‘module1>=2.1.0’, ‘module2==*’, ‘etc’]. And then you can do pipenv install -e . (note the .) to install the requirements you’ve specified. As an extra added bonus, doing this also sets up the pythonpath of the root of the module so that, if you’re in the pipenv venv, you no longer have to worry about relative import paths anywhere in your project.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.