Get AI summaries of any video or article — Sign up free
Python Tutorial: Pipenv - Easily Manage Packages and Virtual Environments thumbnail

Python Tutorial: Pipenv - Easily Manage Packages and Virtual Environments

Corey Schafer·
5 min read

Based on Corey Schafer's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.

TL;DR

pipenv installs packages and automatically creates a per-project virtual environment, eliminating separate setup steps.

Briefing

pipenv is positioned as a single, Python-ecosystem tool that unifies package management and virtual environments—reducing the friction of setting up per-project dependencies while making builds more reproducible. Instead of juggling separate steps for installing packages (pip) and isolating them (virtualenv), pipenv creates the virtual environment automatically, tracks dependencies in a Pipfile, and generates a Pipfile.lock to lock exact versions for consistent installs across machines and deployments.

The workflow starts with installation: pipenv is installed via `pip install pipenv`. From there, a project folder becomes the unit of isolation. Running `pipenv install requests` in an empty project directory triggers multiple actions at once: pipenv detects that no virtual environment exists yet, creates one using the configured Python interpreter (the example uses Python 3.7), writes a Pipfile describing the requested dependencies, installs the package into that environment, and generates a Pipfile.lock when it’s missing. The Pipfile is editable and human-friendly, using TOML syntax with sections like `source`, `packages`, and a `python_version` entry. In the example, `requests = *` appears when no specific version is pinned, meaning pipenv will allow newer versions to be selected on future installs.

That flexibility is paired with determinism through Pipfile.lock. The lock file is generated and treated as non-editable; it records exact package versions plus hashes and dependency details, including transitive dependencies pulled in by packages like requests. This is the mechanism that prevents “works on my machine” drift: the Pipfile can float to newer releases, but the lock file ensures the same environment can be recreated reliably. The video also contrasts development versus production readiness: after testing, updating the lock file with `pipenv lock` captures the known-good dependency set, which can then be moved to production.

pipenv also streamlines common team and lifecycle tasks. Dependencies from an existing `requirements.txt` can be imported using `pipenv install -r requirements.txt`, which updates the Pipfile.lock and installs the listed packages at the exact versions found in that file. For teams still using pip, `pip freeze` has an equivalent: `pipenv lock -r` outputs dependencies in a requirements.txt-compatible format. Dev-only dependencies are handled separately via `pipenv install pytest --dev`, placing packages under a `dev-packages` section so they won’t ship with production installs.

Operational commands round out the toolset: `pipenv shell` opens an interactive subshell inside the environment, while `pipenv run <command>` executes without activating it. Removing packages uses `pipenv uninstall <package>`, and switching Python versions can be done by editing `python_version` in the Pipfile and running `pipenv --python <version>` or by deleting and recreating the environment with `pipenv --rm` followed by `pipenv install`. pipenv adds security and debugging utilities too: `pipenv check` flags known vulnerabilities and suggests upgrades, and `pipenv graph` visualizes the dependency relationships.

Finally, pipenv supports environment-specific configuration via a `.env` file. Creating a project-local `.env` (e.g., `SECRET_KEY=...`) allows Python code to load variables automatically; the example shows reading the value through `os.environ`. The guidance is clear: don’t commit `.env` files to version control (add them to `.gitignore`) because they may contain secrets like database credentials and API keys.

Cornell Notes

pipenv combines pip-style dependency management with virtual environments in one workflow. Installing packages (e.g., `pipenv install requests`) automatically creates a per-project virtual environment, writes a Pipfile describing dependencies, and generates a Pipfile.lock for deterministic builds. Pipfile is editable and can specify flexible versions (like `requests = *`), while Pipfile.lock records exact versions and hashes so the same environment can be recreated reliably. pipenv also supports dev-only dependencies (`--dev`), importing from `requirements.txt` (`-r`), exporting lock data back to requirements format (`lock -r`), and running commands inside the environment (`pipenv shell` / `pipenv run`). It further adds security checks (`pipenv check`), dependency visualization (`pipenv graph`), and project-scoped environment variables via `.env` files.

How does pipenv differ from using pip and virtual environments separately?

pipenv unifies both tasks: it creates and manages the virtual environment while also handling dependency installation. A single command like `pipenv install requests` triggers environment creation (if missing), writes a Pipfile, installs the dependency into that environment, and generates a Pipfile.lock. That replaces the older multi-step process of creating a virtual environment, activating it, then running pip installs.

What roles do Pipfile and Pipfile.lock play, and why does that matter for stability?

The Pipfile is the editable specification of dependencies and the target Python version (using TOML sections like `source`, `packages`, and `python_version`). It can use flexible version specs such as `requests = *`. The Pipfile.lock is generated and treated as non-editable; it records exact package versions, hashes, and transitive dependencies, enabling deterministic builds. This prevents unexpected breakage when newer package versions appear, because production installs can rely on the locked set after testing.

How can dependencies be brought in from an existing requirements.txt file?

pipenv can import them with `pipenv install -r requirements.txt`. In the example, the command reports that it imported the requirements into the Pipfile, updated Pipfile.lock, and installed the dependencies. Afterward, the Pipfile’s `packages` section reflects the exact versions from the imported requirements.

How are dev-only dependencies kept out of production installs?

pipenv supports a dev flag. Installing `pytest` with `pipenv install pytest --dev` adds it to the `dev-packages` section rather than the main `packages` section. That separation is intended so testing tools can be excluded when deploying.

What are the practical ways to run code inside a pipenv-managed environment?

Use `pipenv shell` to launch a subshell with the environment activated (the prompt shows the environment name). Alternatively, skip activation and run a command directly with `pipenv run`, such as `pipenv run Python` to execute Python using the environment’s interpreter and installed packages.

How does pipenv handle security checks and dependency debugging?

`pipenv check` scans installed packages for known vulnerabilities and reports issues, including whether newer versions resolve them. `pipenv graph` prints a dependency graph showing which packages depend on others (e.g., how `pytz` is listed as a dependency of `Django`), which helps trace why certain packages are installed or diagnose conflicts.

Review Questions

  1. What is the difference between specifying `requests = *` in the Pipfile and relying on Pipfile.lock during production deployment?
  2. Which pipenv commands would you use to (1) install dev-only dependencies and (2) export dependencies in requirements.txt format for a team still using pip?
  3. If you change `python_version` in the Pipfile, what steps ensure the virtual environment matches the new interpreter version?

Key Points

  1. 1

    pipenv installs packages and automatically creates a per-project virtual environment, eliminating separate setup steps.

  2. 2

    Pipfile is an editable dependency spec (TOML) that can use flexible version constraints like `*`.

  3. 3

    Pipfile.lock is generated and records exact versions and hashes, enabling deterministic, repeatable builds.

  4. 4

    Import existing dependencies with `pipenv install -r requirements.txt`, and export lock data back with `pipenv lock -r` for compatibility with pip-based teams.

  5. 5

    Use `--dev` to keep testing and other development tools out of production dependency sets.

  6. 6

    Switch Python versions by updating `python_version` in the Pipfile and recreating the environment (or using `pipenv --python <version>`).

  7. 7

    Use `pipenv check` for vulnerability feedback and `pipenv graph` to visualize dependency relationships; manage secrets via a project-local `.env` file without committing it.

Highlights

Running `pipenv install requests` in a new project directory creates the virtual environment, writes a Pipfile, installs the package, and generates a Pipfile.lock.
Pipfile can float to newer versions, but Pipfile.lock pins exact versions and hashes so production installs match what passed testing.
`pipenv install pytest --dev` cleanly separates dev dependencies from production dependencies using a dedicated `dev-packages` section.
`pipenv check` can flag known vulnerabilities and indicate that upgrading (e.g., Django) resolves the reported issues.
A `.env` file placed in the project directory loads environment variables automatically, and it should be excluded from version control to protect secrets.

Topics

Mentioned