Pipenv: 从 Pipfile.lock 生成 requirements.txt

创建于 2019-01-31  ·  25评论  ·  资料来源: pypa/pipenv

如何从现有的Pipfile.lock生成requirements.txt文件而不锁定?
当我运行pipenv lock -r时,它会忽略现有的Pipfile.lock并再次执行锁定过程。

有一个解决方法:

$ pipenv sync
$ pipenv run pip freeze

在我的特殊情况下,我正在构建 docker 映像并在Dockerfile中使用requirements.txt #$ 。 我想避免在主机上创建虚拟环境只是为了能够创建requirements.txt

最有用的评论

你可以跑

pipenv run pip freeze > requirements.txt

所有25条评论

Pipenv 没有为此提供方法,您可以寻找其他 pipfile 实用程序库,例如pipfile-requirements

你可以跑

pipenv run pip freeze > requirements.txt

你可以跑

pipenv run pip freeze > requirements.txt

这就是我在第一篇文章中提到的解决方法。

但它只有在您的 pipenv 环境同步时才有效(安装了所有软件包)。
直接从Pipfile.lock中提取依赖项对我来说更方便:

jq -r '.default
        | to_entries[]
        | .key + .value.version' \
    Pipfile.lock > requirements.txt

博文
jq工具

大声笑,我已经提到过那个图书馆。

我个人不喜欢有一个专门的图书馆。 此外,团队成员很有可能已经安装了jq或其他一些通用工具。

你甚至可以跑

 pipenv lock --requirements > requirements.txt

它不会像您期望的那样工作,因为正如我所写:

当我运行pipenv lock -r时,它会忽略现有的Pipfile.lock并再次执行锁定过程。

换句话说,它执行更新,这可能会破坏分发。 想象一下,您生成requirements.txt以在 Dockerfile 中使用它来构建 docker 映像。 您的应用程序在本地可以工作,但是当您使用pipenv lock生成requirements.txt $ 时,需求可能会更新为不兼容或损坏的版本(但希望这种情况很少见)。 在运行映像之前您不会知道这一点。 因此,您需要在运行pipenv lock后再次测试应用程序。

如果您不想使用jq ,那么最好使用我在第一篇文章中提出的方法pipenv sync (它不会更新)。

@Zebradil您的jq oneliner 方法比@frostming自己的pipfile-requirements包(100多行python代码)简单得多,因为我已经安装jq ,没有其他依赖项必须的,太好了。

但是,在几次 git 提交之后,我注意到pipenv lock --requirements输出的内容与jq通过Pipfile.lock文件收集并打印出来的内容之间的区别:

  • jq输出没有-i https://pypi.org/simple作为第一行,这与pipenv lock --r始终作为第一行插入的内容相反。
  • jq输出不包含包的注释。 例如: pipenv lock --r输出有这一行appnope==0.1.0 ; sys_platform == 'darwin' ,但在jq输出中,它是appnope==0.1.0 。 另一个例子是pipenv lock -r生成pexpect==4.7.0 ; sys_platform != 'win32'jq生成pexpect==4.7.0 ,不确定这是否重要。
  • 两个输出之间的需求文件包顺序不同。 jq大概采用Pipfile.lock文件中的包顺序,它总是按字母和字符长度的升序排序,例如flaskflask-sqlalchemy前面flask-XXXXX包,而pipenv lock --r $ 在flask-sqlalchemy flask $ ,这与Pipfile.lock中的顺序不同。 这是一个主要的烦恼,因为它不会生成最小的 git diff。 我认为这是pipenv中的错误。

@ye ,方法的很好比较。 它可能会帮助人们为他们的特定情况选择适当的解决方案并避免警告。

是的,正如您所说, jq的建议方法功能有限。 可以扩展它以添加注释和包索引 URL,但我现在不需要这个。

为了避免在生成的 requirements.txt 中出现差异,应该考虑每次都使用相同的方法。 同样,使用不同的代码格式化工具可能会导致结果不一致。 所以,我认为这里没有问题。

你可以跑

pipenv run pip freeze > requirements.txt

这就是我在第一篇文章中提到的解决方法。

但它只有在您的 pipenv 环境同步时才有效(安装了所有软件包)。
直接从Pipfile.lock中提取依赖项对我来说更方便:

jq -r '.default
        | to_entries[]
        | .key + .value.version' \
    Pipfile.lock > requirements.txt

博文
jq工具

你好,

感谢您的解决方案。 我遇到了同样的问题,但我还需要pipenv lock -r创建的源的定义,即:-i,--extra-index-url。 这是因为我使用私人资源。

@Zebradil我认为您提到了这一点。

因此,我在 python 中创建了另一个包含该功能的最小无依赖关系脚本。 如果您在 Pipfile 中以这种方式定义了源,它还会扩展 env var。

如果有人想看看,我会把它留在这里: https ://gist.github.com/rcastill/dab85c234dd10fa7af56755116c75aee

如果它对其他人有帮助,以下是如何在结果中包含散列:

 jq --raw-output '.default | to_entries[] | .key + .value.version + (.value.hashes | map(" --hash=\(.)") | join(""))' Pipfile.lock

这会创建类似的条目

paramiko==2.6.0 --hash=sha256:99f0179bdc176281d21961a003ffdb2ec369daac1a1007241f53374e376576cf --hash=sha256:f4b2edfa0d226b70bd4ca31ea7e3893259907283da2304865d

这使得pip强制执行哈希。

如果您只想包含原始需求文件中的需求(前提是它们已经使用==锁定到特定版本):

 jq --raw-output '.default | to_entries[] | .key + .value.version + (.value.hashes | map(" --hash=\(.)") | join(""))' Pipfile.lock | grep --file=<(grep --only-matching --perl-regexp '^.*(?===)' requirements.txt | tr '[:upper:]' '[:lower:]') > new.txt && mv new.txt requirements.txt

tr是必需的,因为 requirements.txt 文件可能包含混合大小写的包名称,但pipenv install -r requirements.txt在 Pipfile 中将它们小写。

这是一个小 Python 脚本,以防您想将Pipfile (不是锁定文件)转换为 requirements.txt 文件。

import configparser


def main():
    parser = configparser.ConfigParser()
    parser.read("Pipfile")

    packages = "packages"
    with open("requirements.txt", "w") as f:
        for key in parser[packages]:
            value = parser[packages][key]
            f.write(key + value.replace("\"", "") + "\n")


if __name__ == "__main__":
    main()

@frostming嗨,我发现https://github.com/frostming/pipfile-requirements很有用,但为什么它没有集成到 pipenv 中?

@linusguan该工具是为那些不想安装大pipenv库的人而存在的,当你安装了pipenv时,你可以使用pipenv lock -r

@frostming我发现它与不支持 pipfile.lock 的其他工具一起使用非常有用。
pipenv lock -r的问题是它更新了 pipfile.lock 所以我不能使用它来生成确定性构建以及其他工具。 像pipenv lock -r --ignore-pipfile这样的东西是理想的。

这是另一个使用哈希从 Pipfile.lock 文件生成 requirements.txt 的 python 脚本:

import os
import json

__dir__ = os.path.dirname(os.path.realpath(__file__))


def read_json_file(path):
    with open(path) as f:
        return json.load(f)


def main():
    root = read_json_file(os.path.join(__dir__, 'Pipfile.lock'))

    for name, pkg in root["default"].items():
        version = pkg["version"]
        sep = lambda i: "" if i == len(pkg["hashes"]) - 1 else " \\"
        hashes = [f'--hash={t}{sep(i)}' for i, t in enumerate(pkg["hashes"])]
        tail = '' if len(hashes) == 0 else f' {hashes[0]}'
        print(f'{name} {version}{tail}')
        for h in hashes[1:]:
            print(f'    {h}')


if __name__ == "__main__":
    main()

@Zebradil谢谢! 你的解决方案真的对我有用。

  • 我首先使用brew install jq安装jq工具
  • 然后使用您的脚本从Pipfile.lock生成requirements.txt #$

看起来这可以用--keep-outdated标志解决,还是我弄错了?

pipenv lock --keep-outdated -d -r > requirements.txt

PS这是一个令人讨厌的冗长标志来解决这个问题

不幸的是@jacobisaliveandwell --keep-outdated 标志似乎更新了子依赖项: https ://github.com/pypa/pipenv/issues/3975

@paytonrules这是一个错误,但旗帜的精神仍然是这个问题的答案。

PS不需要为此大拇指向下:-(

只想提一下,从所述的解决方法中,存在差异:
pipenv run pip freeze返回区分大小写的包名称(例如PyYAML
pipenv lock --requirements返回所有小写包名(例如pyyaml

@Darkless012您应该打开另一张描述该问题的票证,并将此问题作为相关参考。

纯 bash,只是包,没有别的,以防有人不能或不想安装 jq,以防万一它对某人有帮助,

cat Pipfile.lock \
  | grep -B1 '"hashes"\|"version": ' \
  | grep -v '"markers": \|"hashes": ' \
  | grep ": {\|version" \
  | sed -e 's/: {$//g' \
  | tr '\n' ',' | tr -s ' ' ' ' \
  | sed -e 's/, "version": "//g;s/", "/ /g;s/"//g;s/,//g' \
  | tr ' ' '\n' \
| grep -v "^$" > requirements.txt

是否有任何东西也可以将散列从 Pipfile 复制到 requirements.txt(例如,给定类似平台 str 的东西)以便pip install --require-hashes起作用?

$ pip install --help
# ...
  --require-hashes            Require a hash to check each requirement against, for repeatable installs. This option is implied when any package in a
                              requirements file has a --hash option.

您可以使用 micropipenv,它可以将 Pipenv.lock(也是诗歌锁)文件转换为 requirements.txt(原始 requirements.txt 或 pip-tools 兼容)。 见https://github.com/thoth-station/micropipenv/#micropipenv -requirements--micropipenv-req

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

Californian picture Californian  ·  3评论

FooBarQuaxx picture FooBarQuaxx  ·  3评论

AkiraSama picture AkiraSama  ·  3评论

jeyraof picture jeyraof  ·  3评论

leileigong picture leileigong  ·  3评论