Pipfile.lock → requirements.txt
TL;DR
Update
As it was pointed out in the comments, in the v2022.4.8 release a new command is added, which does the desired:
|
|
Here is the documentation for the command.
Old approach
For requirements.txt
:
|
|
For requirements-dev.txt
:
|
|
Explanation
I intensively use Python at my job.
And Pipenv is a must for managing packages and virtual environments.
It keeps all dependencies in Pipfile
and lock their precise versions in Pipfile.lock
.
Although it’s a great tool in development, sometimes we still need requirements.txt
file.
As an example I will use building a docker container image with python environment inside.
In our case first caveat was that we were using pipenv install
during container build.
This command (surprisingly) doesn’t just install all packages with the versions from Pipfile.lock
as we expected, but
update dependencies with lock
subcommand first and then run sync
subcommand to actually install them.
Because the lock
subcommand updates packages only to versions compatible with the ones specified in Pipfile
,
It might be not a problem as far as versions in Pipfile
are restrictive enough.
In the other case, one can get a broken distribution even if an application was working locally.
After discovering this behavior of Pipenv, to avoid such issues we started using pipenv sync
directly.
But in the next time our build process was broken by buggy update of Pipenv itself. So, we had to fix Pipenv version during installation in inside Dockerfile.
And afterwards I got an idea that we, actually don’t need Pipenv inside containers at all.
It was used only as a wrapper on pip for parsing Pipfile.lock
.
We just need to provide requirements.txt
file and use pip on it.
There is an official way
to generate requirements.txt
with Pipenv:
|
|
It works, however, it has the before mentioned side-effect and there is no pipenv sync -r
alternative.
Someone even created pipenv-to-requirements python package for requirements.txt
generation.
I haven’t tried it, because I found another way.
Sometimes I need to operate with JSON data in terminal and jq is really powerful tool for that, check it if you haven’t seen it.
I thought that I can generate requirements.txt
with jq, as far as Pipfile.lock
is a json file.
So, this is how it looks like:
|
|
-r
is needed to get unquoted output.defailt
gets content of thedefault
section insidePipfile.lock
, change to.develop
to generaterequirements-dev.txt
to_entries[]
transformspackage: info
pair to an object{"key": package, "value": info}
and pack them to an array.key + .value.version
builds a string of package name and it’s version
Look inside Pipfile.lock
for better understanding.