Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Using Pipenv

00:00 In the previous lesson, I showed you how to use pip and where it puts any installed packages. In this lesson, I’ll introduce you to using pipenv to manage both your package installation and virtual environments.

00:13 In the previous lesson, you saw some of the problems of using pip on its own without a virtual env. If you have multiple projects with conflicting dependencies, keeping everything in the same site-packages directory is problematic.

00:25 A common way of managing your package versions is by including their information in a requirements.txt file. This also has some problems. If you only include your dependencies and not your dependents’ dependents inside of your requirements.txt file, your build won’t be deterministic.

00:43 Think back to the example of installing requests in the previous lesson. requests is dependent on certifi, amongst other things.

00:51 If certifi releases something new, your next installation will end up using a different set of libraries than your first installation. This is a good way for dev and production to be mismatched and can result in a “worked on my machine” kind of problem.

01:05 So instead of specifying only requests in your requirements.txt, you could redirect pip freeze and grab all the dependencies like I showed you in the previous lesson. This solves the problem above, but also means you’re now responsible for all of the packages.

01:21 You might want to get that new version of certifi because of a bug fix. Keeping everything in requirements.txt means you’re managing all of it.

01:30 Lastly, requirements.txt is one flat file, meaning it can only specify a single environment. What if your dev environment needs testing packages that your production environment doesn’t require?

01:41 I have seen some package maintainers have requirements and dev-requirements files, which works. But now you’ve got twice the things you have to maintain. As you might’ve guessed, like a late-night TV commercial talking about all the problems of dull knives, I’ve got a sharper knife to sell you. pipenv solves most of these problems.

01:59 If you hadn’t heard of it before, pipenv is a third-party tool maintained by the same people who maintain the core Python libraries. it uses pip and virtualenv under the hood to give you that sharper knife.

02:13 You may recall from the previous lesson that I did some of the work in a directory called without_pipenv. That is because pipenv does some magic things if it finds a requirements.txt file. So to avoid that, I’m going to create a new directory called using_pipenv and stay inside of that one to avoid any side effects.

02:34 pipenv itself is a third-party package, so the first step is to install it.

02:43 It is okay to have this in your site-packages directory, as you’re always going to want it. Once this is in place, it will be virtual envs from here on in. Let me just scroll up a bit.

02:55 Nothing here you haven’t seen before. Package is installed, along with all of its dependencies.

03:02 I’m going to create a new project called hola.

03:09 To create a new virtual environment, you use the pipenv shell command.

03:17 The shell command is used for entering a virtual environment, but if it doesn’t find one, it creates it, like in this case. There are a few things going on here. First off, it tells you that it is creating a virtual environment and a Pipfile.

03:31 The Pipfile is one of two files used to specify your packages. I’ll get into details with those in a second. Next, it tells you what version of Python it’s going to use. In my case, it was C-Python 3.10.

03:43 It also adds some useful base packages to the virtual environment—those for doing package management, pip, setuptools, and wheel. Four lines from the bottom, it tells you where the virtual env files will be stored.

03:55 pipenv uses a centrally located place for all of its files. Your location is OS specific. Mine is my home directory .local/share/virtualenvs. Note that it names the virtual env with the name of my directory and a hash.

04:10 This naming is how it knows which environment to activate on subsequent calls to the shell command. Finally, pipenv activates my virtual environment.

04:19 You can see that it modifies the prompt to tell me what environment and directory I am in. Depending on your settings, this may also include your host and username information.

04:30 The virtual environment is created in a central location, but creating it creates a local file, Pipfile. This, combined with another file called Pipfile.lock, is the replacement for requirements.txt.

04:43 These files specify information about the packages you’re using in your project. Let’s take a look at one.

04:52 Here’s the default Pipfile before you install anything. It uses the TOML format, which is similar to Windows INI files. Sections in the file are denoted by double square brackets, and the sections themselves contain key/value pairs.

05:07 The source section specifies where to get packages from. This defaults to the PyPI repository. The packages and dev-packages section specifies packages that are installed. Right now, these are empty, and the requires section specifies the version of Python being used.

05:25 Now that you’ve seen the file, let’s install something and look at the difference. Let’s repeat what was done in the previous lesson, but this time in a virtual environment.

05:39 The command is similar, but this time it is pipenv install. The output is a bit different, but the result is the same. The package is installed.

05:49 pipenv doesn’t bother telling you about what requests depends on. It just updates the files. Looking in the directory, you’ve now got both a Pipfile and a Pipfile.lock.

06:01 Let’s look inside of them. Here’s the state of the Pipfile after I did the installation. The only change here is to the packages section. It has an entry for the requests package.

06:14 The asterisk there indicates that any version of requests is allowed—i.e., it should grab the most recent. It did that because I didn’t ask for a specific version when I did the installation. After you’ve done the installation, you can always edit the Pipfile to change the behavior, so if you wanted to pin requests, you could do that by editing this file.

06:36 That being said, you don’t normally do that because the other file, the lock file, is for pinning.

06:44 Pipfile specifies what packages you install. Pipfile.lock contains a fully pinned listing of all the dependencies. If you want a production environment that exactly mimics your dev environment, you can do an installation with the lock file instead. On the other hand, as you’re developing, if all you care about is the libraries you installed, you can continue to use the Pipfile itself and then create a new lock when you’re ready to go. The format of the lock file is JSON.

07:14 It is made up of a series of nested dictionaries. The first part here specifies some metainformation and indicates what version of the Pipfile spec is being used and which Python version. The third section states where the libraries were sourced from, in this case the PyPI repository.

07:33 The next section of the lock file contains an entry for each of the libraries installed in the virtual environment. Each library is named, has a hash describing its contents, and fully pins a version. On the screen right now are the pinned versions of certifi, charset-normalizer, and idna.

07:52 Wow, lots of screenfuls of lock files. This is the last one. The default section continues on this screen here, pinning the requests and urllib3 libraries.

08:04 Finally, at the bottom, there’s a section for libraries only to be used in the dev environment, which at the moment is empty. Let’s play around with pipenv some more.

08:16 Before showing you the contents of Pipfile and Pipfile.lock, I was inside of the hola virtual environment. Back in the terminal now, I use the exit command to get out of that shell.

08:28 Let’s create another project.

08:38 Running pipenv shell inside of the new salve directory creates a new virtual environment and activates it. Just like pip, pipenv install supports the -e argument.

08:49 Remember the hello package? Let’s try it again.

08:58 So far, so good. And now the bonjour package.

09:07 Well, that didn’t go well. Unlike pip, pipenv has a very strong opinion about conflicts. It won’t let you do it by default. Let me scroll up just a bit here.

09:26 pipenv attempted to create the lock file, and the locking failed because of the conflict. And it explicitly tells you that. About halfway down here, you’ll see the keyword critical, and it tells you exactly what conflict happened: colorama-0.3.9 and 0.4.4 were specified by two different libraries. If I scroll back down, you’ll see it even gives you some suggestions as to what you can do about it.

09:54 Now, if you want to shoot yourself in the foot, you’re going to have to do it explicitly. pipenv puts the safety on the gun and gives you steel-toe boots.

10:03 You can still pull the trigger, but it shouldn’t happen by accident.

10:08 You’ve seen the basics, but wait, there’s more! It slices, it dices, it even juliennes! Next up, more pipenv goodness.

Become a Member to join the conversation.