Why does pipenv need Pipfile and Pipfile.lock?
Question:
(I think[!]) I understand the principles behind pipenv
(and the other venvs) and frequently use them. However, I’ve never really understood why pipenv
needs both a Pipfile
and a Pipfile.lock
file.
This answer implies, and this tutorial says
Now, once you get your code and Pipfile.lock in your production
environment, you should install the last successful environment
recorded:
$ pipenv install --ignore-pipfile
but it doesn’t explain why Pipfile.lock
needs to be used. i.e. what does the .lock
file contain that Pipfile
doesn’t, and why is Pipfile
good enough to be shared with another developer:
Now let’s say another developer wants to make some additions to your
code. In this situation, they would get the code, including the
Pipfile, and use this command:
$ pipenv install --dev
but isn’t good enough to be used to replicate your environment in production?
Answers:
The official Pipfile project has something to say about this:
The concrete requirements for a Python Application would come from Pipfile
. This would include where the packages should be fetched from and their loose version constraints.
The details of the environment (all installed packages with pinned versions and other details) would be stored in Pipfile.lock
, for reproducibility. This file will be automatically generated and should not be modified by the user.
In other words, Pipfile
is for people and Pipfile.lock
is for computers.
In your Pipfile
you list the things you want, and you define them in a somewhat loose way like "Django version 2 or greater". But that’s not good enough to deterministically reproduce an environment. Does that mean "Django 2.0.3" or "Django 2.1.0"?
Pipfile.lock
specifies requirements exactly, and it also specifies dependencies exactly. For example, if you explicitly want foo
and put that into your Pipfile
, your Pipfile.lock
will be generated locking that down to a specific version. If foo
itself depends on bar
, and bar
depends on quux
and florp
, the Pipfile.lock
file will lock bar
, quux
, and florp
down too, so minor differences in dependencies don’t break things.
As @Chris has said, Pipfile.lock
is for computer while Pipfile
is for human. If you take a look at Pipfile.lock
file, you will find that every dependency even has sha256 codes!
That file is impossible for human to deal with, you can only deal with Pipfile
. But Pipfile
is not strict enough to reproduce a totally same environment. So that’s why we also need a Pipfile.lock
.
This is a tool like npm.(maybe?)
The Pipfile
is to identify the dependency of your project, you will get the dependency tree from the Pipfile
.
But according to the different source, your will get different packages. So you can get actual local dependency from .lock
file.
For example, in Pipfile, you can see something like:
matplotlib = "*"
numpy = "*"
But in .lock
file, you will see the actual dependency like:
"pytz": {
"hashes": [
"sha256:a061aa0a9e06881eb8b3b2b43f05b9439d6583c206d0a6c340ff72a7b6669053",
"sha256:ffb9ef1de172603304d9d2819af6f5ece76f2e85ec10692a524dd876e72bf277"
],
"version": "==2018.5"
}
In short, Pipfile
is to be more compatible, but .lock
file is to get the actual dependency in local.
(I think[!]) I understand the principles behind pipenv
(and the other venvs) and frequently use them. However, I’ve never really understood why pipenv
needs both a Pipfile
and a Pipfile.lock
file.
This answer implies, and this tutorial says
Now, once you get your code and Pipfile.lock in your production
environment, you should install the last successful environment
recorded:$ pipenv install --ignore-pipfile
but it doesn’t explain why Pipfile.lock
needs to be used. i.e. what does the .lock
file contain that Pipfile
doesn’t, and why is Pipfile
good enough to be shared with another developer:
Now let’s say another developer wants to make some additions to your
code. In this situation, they would get the code, including the
Pipfile, and use this command:$ pipenv install --dev
but isn’t good enough to be used to replicate your environment in production?
The official Pipfile project has something to say about this:
The concrete requirements for a Python Application would come from
Pipfile
. This would include where the packages should be fetched from and their loose version constraints.The details of the environment (all installed packages with pinned versions and other details) would be stored in
Pipfile.lock
, for reproducibility. This file will be automatically generated and should not be modified by the user.
In other words, Pipfile
is for people and Pipfile.lock
is for computers.
In your Pipfile
you list the things you want, and you define them in a somewhat loose way like "Django version 2 or greater". But that’s not good enough to deterministically reproduce an environment. Does that mean "Django 2.0.3" or "Django 2.1.0"?
Pipfile.lock
specifies requirements exactly, and it also specifies dependencies exactly. For example, if you explicitly want foo
and put that into your Pipfile
, your Pipfile.lock
will be generated locking that down to a specific version. If foo
itself depends on bar
, and bar
depends on quux
and florp
, the Pipfile.lock
file will lock bar
, quux
, and florp
down too, so minor differences in dependencies don’t break things.
As @Chris has said, Pipfile.lock
is for computer while Pipfile
is for human. If you take a look at Pipfile.lock
file, you will find that every dependency even has sha256 codes!
That file is impossible for human to deal with, you can only deal with Pipfile
. But Pipfile
is not strict enough to reproduce a totally same environment. So that’s why we also need a Pipfile.lock
.
This is a tool like npm.(maybe?)
The Pipfile
is to identify the dependency of your project, you will get the dependency tree from the Pipfile
.
But according to the different source, your will get different packages. So you can get actual local dependency from .lock
file.
For example, in Pipfile, you can see something like:
matplotlib = "*"
numpy = "*"
But in .lock
file, you will see the actual dependency like:
"pytz": {
"hashes": [
"sha256:a061aa0a9e06881eb8b3b2b43f05b9439d6583c206d0a6c340ff72a7b6669053",
"sha256:ffb9ef1de172603304d9d2819af6f5ece76f2e85ec10692a524dd876e72bf277"
],
"version": "==2018.5"
}
In short, Pipfile
is to be more compatible, but .lock
file is to get the actual dependency in local.