Python Tutorial: Pipenv - Easily Manage Packages and Virtual Environments
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.
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?
What roles do Pipfile and Pipfile.lock play, and why does that matter for stability?
How can dependencies be brought in from an existing requirements.txt file?
How are dev-only dependencies kept out of production installs?
What are the practical ways to run code inside a pipenv-managed environment?
How does pipenv handle security checks and dependency debugging?
Review Questions
- What is the difference between specifying `requests = *` in the Pipfile and relying on Pipfile.lock during production deployment?
- 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?
- If you change `python_version` in the Pipfile, what steps ensure the virtual environment matches the new interpreter version?
Key Points
- 1
pipenv installs packages and automatically creates a per-project virtual environment, eliminating separate setup steps.
- 2
Pipfile is an editable dependency spec (TOML) that can use flexible version constraints like `*`.
- 3
Pipfile.lock is generated and records exact versions and hashes, enabling deterministic, repeatable builds.
- 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
Use `--dev` to keep testing and other development tools out of production dependency sets.
- 6
Switch Python versions by updating `python_version` in the Pipfile and recreating the environment (or using `pipenv --python <version>`).
- 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.