Introduction
Pipenv is Python's officially recommended Package management tool, as the name suggests it combines the power of
pip
and
virtualenv
. It is really powerful and gives control of package management for a python project. It also has support for adding dev packages, python versions, smartly recognizing main and derived package installation/uninstallation, and so on. It is the
official package management tool for Python
.
It is quite similar to npm for Nodejs in Javascript, or bundle for Ruby, cargo for Rust, and so on. It really simple and easy to use as it manages the overhead for package management for us and hence it is also a high-level package management tool as opposed to pip, which is not as powerful as Pipenv. So, in this article, we'll explore Pipenv package manager for Python and how you can use it in your next python project. Let's get started.
Install Pipenv
Pipenv is just like any other package in python, you can install it with pip as normally you install any other package with the command:
pip install pipenv
You can refer to the documentation of Pipenv from here .
Set up a Python Environment
This step is not mandatory but it avoids any mistakes that you can make in the future while installing the package, so to simply create a new python environment for your project, you simply have to write the following command:
pipenv shell
This will create the virtual environment for Python in the local folder. It is quite similar to installing
virtualenv
and then activating the env/venv folder script. Though pipenv is quite powerful as it automatically detects the environment.
If you look at it carefully, there will be a file generated after the command has been executed successfully. The file called
Pipfile
without any extension will have been created in your current folder where you executed the command from. The file contains the version of python used in this project along with the list of dependencies(currently empty). Also the source from where it will download and manage the dependencies.
The Pipfile after simply creating the virtualenv via the command
pipenv shell
looks something like follows:
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
[dev-packages]
[requires]
python_version = "3.8"
If you want to set up a specific version of python for the virtual environment, you can do this using pipenv. The version should be installed in your system though for the pipenv to pick it up, if you have the specific version of python set up with all path variables configured, you can use the below command to set up the version of python in pipenv.
pipenv --python version-number
For example :
pipenv --python 3.9
will set up the virtual environment with python version
3.9
.
What is Pipfile
Pipfile is basically a TOML file that has all the details of the different dependencies/packages and the version of Python used in the project/directory. A TOML is a simple configuration file that is reader-friendly, it is a map of keys and values as configuration data structures. In Pipenv, we can have keys like
package-names
and the value as the
version-number
, certain groups of dependencies like
dev-packages
and
packages
, etc. Pipenv is the file that Pipenv implements its package management environment. The file is really important and powerful as it can install all dependencies even if provided with
requirements.txt
file. Yes, it can automatically detect that if you provide the path to that file.
Pipenv also has additional features like adding dev dependencies/packages in the project as a separate dependency. So if you want to test a feature with a specific package you can add it as a dev package and it will be stored separately. The pipfile will segregate the dependencies so that Pipenv can install/uninstall from the virtual environment. In short, Pipfile lets you have great control over your project's packages management.
Installing Python Packages
Once your Pipenv is initialized as a virtual environment for Python, we can install dependencies with either
pip
or
pipenv
. This is the mistake that might get you trapped, if you already have not run the command
pipenv shell
and installed any dependencies with
pip
, you will install that dependency globally and make some mess of the project. So, it is advised to use
pipenv shell
in order to activate your virtual environment. If you do not wanna do that, you can use the command to install any dependency without activating the virtual environment.
pipenv install <package-name>
This will detect any virtual environment in the project, if it's not created already it will create it and install that package in that environment.
Installing any package using
pipenv
will update the Pipenv file and the package to its packages list.
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
flask = "*"
[dev-packages]
[requires]
python_version = "3.8"
OR
If you wish to install with pip, as usual, you need to be in the virtual subshell. If you already are, then Pipenv will add that dependency to the virtual environment. Note though, if you install any package with
pip
and not with
pipenv
, the package won't be added to Pipfile but would be installed in the virtual environment.
Here, if we type the command
pipenv graph
it will show us a nice detailed list of all the installed dependencies.
pipenv graph
$ pipenv graph
Flask==2.0.3
- click [required: >=7.1.2, installed: 8.0.4]
- colorama [required: Any, installed: 0.4.4]
- itsdangerous [required: >=2.0, installed: 2.1.1]
- Jinja2 [required: >=3.0, installed: 3.0.3]
- MarkupSafe [required: >=2.0, installed: 2.1.0]
- Werkzeug [required: >=2.0, installed: 2.0.3]
requests==2.27.1
- certifi [required: >=2017.4.17, installed: 2021.10.8]
- charset-normalizer [required: ~=2.0.0, installed: 2.0.12]
- idna [required: >=2.5,<4, installed: 3.3]
- urllib3 [required: >=1.21.1,<1.27, installed: 1.26.8]
As you might have guessed, the above command is equivalent to the
pip freeze
command, but just compare the details both tools have. Pipenv really shines here.
If you compare the output of Pipfile and
pipenv graph
you get a bit confused as to why is there are so fewer packages in the file. So,
Pipfile doesn't store the sub-packages/dependencies of a certain base package
. Let's take, for example, Flask here, we have Flask as the main package, and
click
,
Jinja2
,
Werkzeug
are its sub dependencies, further
colorama
and
MarkupSafe
are in turn dependencies of
click
and
Jinja2
. So, Pipfile just includes the top-level packages, pipenv is smart enough to install the rest. It also doesn't include
requests
but it is indeed included in the
graph
. This is because Pipenv will only put the dependencies in the Pipfile if it has been installed via the
pipenv
command.
You can use
pip freeze
here as well as we are technically in a Python virtual environment. And you can clearly see the difference. Pipenv is a high-level tool compared to pip, it technically uses
pip
and
virtualenv
and leverages both of them to become a smart package management tool.
What is the Pipfile.lock
-
If you are coming from
Javascript
world, it is similar topackage-lock.json
file. -
If you are coming from
Ruby
world, it is similar to theGemfile.lock
file. -
If you are coming from
Rust
world, it is similar to thecargo.lock
file.
Ok, you get the idea, it is a file that more robustly specifies the version of the packages without conflicting with the other version or the Python version itself. If you look at the Pipfile.lock also has hashes that store the sub-packages as well. The file format here is JSON as opposed to TOML for the Pipfile.
Configuring the Pipenv environment
Now, a question you might have is where is the virtual environment? Is it there? Of course, it will be there, it is configured to a different location though. By default, it will be stored in the
~\.virtualenvs\
folder.
You can get the location of the current virtualenv with the following command:
pipenv --venv
$ pipenv --venv
C:\Users\acer\.virtualenvs\pipenv-blog-gHY6vF9t
acer
) followed by the hidden folder
virtualenvs
, this folder will contain all the virtualenvs for different projects using
pipenv
.
If you wished to change this location and keep the virtual environment folder in the same directory as your project, you can set up the environment variable for it as follows:
For Linux/macOS:
Add the following to your
~/.bashrc
or other equivalent shell configuration file.
export PIPENV_VENV_IN_PROJECT="enabled"
For Windows:
Add it to the PATH Environment variable.
set PIPENV_VENV_IN_PROJECT="enabled"
This will make sure the virtualenvs for the project in
pipenv
are created inside the current folder itself and not in a single
~\.virtualenvs\
folder.
Creating the requirements.txt file
Let's say you also want to create a requirements.txt file for distributing your project to someone else, as not everyone will use Pipenv to manage their dependencies. It is really straightforward and quick to create a requirements.txt file from the Pipenv environment.
The below command will make the
requirements.txt
file from the existing Pipenv project.
pipenv lock -r >requirements.txt
This will create the requirements.txt file, based on the Pipfile. Pipenv is smart again to provide all of the required dependencies to the requirements.txt in order that pip will be able to install all the required dependencies.
Using requirements.txt in Pipenv
We can install all the dependencies from the requirements.txt file while we are migrating from bare-bones virtualenv and pip to Pipenv. Pipenv will install all the mentioned dependencies and it will also add its checks for the appropriate checks for dependencies.
pipenv install -r requirements.txt
Managing Dev Packages
Let's say we want to install a package but we are not sure to use it in production or the actual script, just a test for how it will work. Thus we have dev packages to install optional or testing packages.
To install a dev-dependency or package, you can install via the following command:
pipenv install <package-name> --dev
If we see the Pipfile, the
django
package that we installed tagged with
--dev
will be in the
dev-packages
$ cat Pipfile
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
flask = "*"
[dev-packages]
django = "*"
[requires]
python_version = "3.8"
If we wanted to uninstall all the dev-packages, we can simply enter the command:
pipenv uninstall --all-dev
This will simply uninstall all the dev dependencies/packages from the pipenv environment and also remove them from the packages list in Pipfile. If you wished to uninstall a specific package in pipenv, you can uninstall it by the simple command:
pipenv uninstall <package-name>
````
## Installing/Uninstalling all packages
To install only the default packages and not dev-packages.
To install or configure a project, if you want to test the project with all the dev dependencies, you can install them with:
This will install all the packages both `packages` and `dev-packages`.
If you want to uninstall all the packages in pipenv, you can use the command :
This will uninstall all the default and dev packages from pipenv. This is like starting a fresh virtual environment.
References:
Conclusion
So, this was a brief introduction to
pipenv
which is Python's recommended package management tool. We saw that we have control over the dependencies and packages in a virtual environment which is taken care of automatically for us. We don't have to activate the environment to install or manage any package for a project.