Python
Pipfile
Pipfile.lock
Dependency Management
Python Packaging

How are Pipfile and Pipfile.lock used?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Pipfile and Pipfile.lock are part of the pipenv workflow for Python dependency management. The short version is: Pipfile declares the packages you want at a high level, and Pipfile.lock records the exact resolved versions that should actually be installed.

That split is important because it separates intent from reproducibility. One file says what the project depends on in human terms. The other says exactly what was resolved so teammates and deployment systems get the same environment.

What Goes in Pipfile

Pipfile is the source file you edit directly. It usually contains:

  • package names,
  • version ranges,
  • development-only dependencies,
  • and sometimes Python version requirements.

Example:

toml
1[[source]]
2url = "https://pypi.org/simple"
3verify_ssl = true
4name = "pypi"
5
6[packages]
7flask = "*"
8requests = ">=2.31"
9
10[dev-packages]
11pytest = "*"
12black = "*"
13
14[requires]
15python_version = "3.12"

This file is readable and intentionally high level. It does not try to pin the entire transitive dependency tree by hand.

What Goes in Pipfile.lock

Pipfile.lock is machine-generated. It records the fully resolved dependency graph, including exact versions and integrity hashes.

You usually do not edit it manually. Instead, pipenv creates or updates it for you.

Typical workflow:

bash
pipenv install flask requests
pipenv install --dev pytest black

After that, pipenv updates both files:

  • 'Pipfile gets the top-level dependency declarations'
  • 'Pipfile.lock gets the exact locked versions'

That lock file is what gives you reproducible installs.

Day-to-Day Workflow

The normal lifecycle looks like this:

  1. Add or change dependencies with pipenv install.
  2. Commit both Pipfile and Pipfile.lock.
  3. On another machine, recreate the environment from the lock file.

Example:

bash
pipenv sync

pipenv sync installs exactly what is listed in Pipfile.lock. That is usually the best choice for CI and deployment because it avoids accidental dependency drift.

If you instead run:

bash
pipenv install

pipenv may update the lock file depending on the situation. That behavior is often fine for local development, but less desirable in automated systems where you want strict reproducibility.

Why Both Files Matter

If you keep only Pipfile, teammates may resolve slightly different transitive versions at different times. If you keep only Pipfile.lock, the project becomes harder to maintain because the high-level dependency intent is less obvious.

Together they solve different problems:

  • 'Pipfile is the editable declaration of what the project needs.'
  • 'Pipfile.lock is the reproducible snapshot of exactly what was resolved.'

This is conceptually similar to other ecosystems that separate manifest files from lock files.

Development Dependencies Versus Production Dependencies

One of the nicer parts of Pipfile is the built-in split between regular packages and development packages.

For example:

bash
pipenv install django
pipenv install --dev pytest

Now the application runtime dependency and the test dependency are stored separately. That makes the project intent clearer and avoids treating every tool as if it were required in production.

Version Control Best Practice

For application projects, the usual best practice is to commit both files to version control. That allows:

  • reproducible local setups,
  • reproducible CI installs,
  • safer debugging when dependency behavior changes,
  • and clearer pull requests when packages are upgraded.

A package library may choose a slightly different strategy depending on how much flexibility it wants to allow consumers, but for deployable applications, committing the lock file is usually the right move.

A Small Example Workflow

Create a new project:

bash
pipenv --python 3.12
pipenv install requests
pipenv install --dev pytest

Run a command inside the managed environment:

bash
pipenv run python -c "import requests; print(requests.__version__)"

Later, after changing dependencies:

bash
pipenv lock
pipenv sync

That sequence keeps the lock file updated and lets another environment install the same resolved versions.

Common Pitfalls

One common mistake is editing Pipfile.lock by hand. It is generated output, so manual edits are brittle and usually get overwritten anyway.

Another mistake is committing Pipfile but not Pipfile.lock for an application. That makes environments less reproducible and turns dependency resolution into a moving target.

It is also easy to use pipenv install in CI when you really wanted pipenv sync. sync is stricter and better aligned with the lock file model.

Finally, some teams mix requirements.txt, Pipfile, and Pipfile.lock without a clear reason. That tends to create confusion about which file is the real source of truth.

Summary

  • 'Pipfile declares top-level dependencies and version intent.'
  • 'Pipfile.lock records the exact resolved dependency versions and hashes.'
  • Edit Pipfile through pipenv commands, not by hand-editing the lock file.
  • Commit both files for application projects so installs stay reproducible.
  • Prefer pipenv sync in CI and deployment when you want exact lock-file installs.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.