一个生成您Python包的nix表达式的工具,因此您不必这样做。
项目描述
pypi2nix 是一个命令行工具,可以从不同的 requirements.txt 生成 Nix表达式。这对于
构建一个用于Python程序的Nix衍生物,作为其打包的一部分。
设置一个用于修改Python程序的开发环境。
我们能够修复pypi2nix的bug的唯一方法是您报告它们。如果您发现问题,请创建一个问题。
pypi2nix 将(除非另行通知)仅与最新的 不稳定 通道一起工作。这是由于Nixpkgs中Python基础设施的持续变化。
如果您尚未阅读,请阅读 Nixpkgs手册中的Python部分。
1. 安装
pypi2nix 是 nixpkgs 的一部分。如果您只想在系统上使用 pypi2nix,建议您通过常规方式安装,例如在 NixOS 上使用 nix-env -iA nixos.pypi2nix 或在其他使用 nix 的系统上使用 nix-env -iA nixpkgs.pypi2nix。
系统要求
确保已安装 Nix
% curl https://nixos.org/nix/install | sh
目前,pypi2nix 仅在 linux 系统上进行测试。支持的 nixpkgs 通道是 nixos-19.09 和 nixos-unstable。由于 nixos-unstable 的特性,偶尔 pypi2nix 会出现故障,这是可以预见的。我们努力及时提供相关修复。
临时安装(简单)
如果您只想使用命令安装软件包,请使用 nix-env
nix-env -if https://github.com/nix-community/pypi2nix/tarball/master
声明性安装(高级)
如果您更喜欢在 Nix(OS) 或项目配置中显式声明每个已安装的软件包,您可以执行以下操作
首先,通过使用 pkgs.fetchgit 获取整个 Git 存储库从其 default.nix 导入软件包。之后,您可以将导入的属性添加到已安装软件包的列表中。
以下是一个 NixOS 的 configuration.nix 示例。其他方法,如 home-manager,操作类似。
let pypi2nix = import (pkgs.fetchgit { url = "https://github.com/nix-community/pypi2nix"; # adjust rev and sha256 to desired version rev = "v2.0.1"; sha256 = "sha256:0mxh3x8bck3axdfi9vh9mz1m3zvmzqkcgy6gxp8f9hhs6qg5146y"; }) {}; in environment.systemPackages = [ # your other packages pypi2nix ];
2. 使用
生成 Nix 表达式最简单的方法是调用
% pypi2nix -e packageA -e packageB==0.1
如果您还有 Python 项目的 requirements.txt 文件,您可以使用 -r 选项。
% pypi2nix -e packageA -e packageB==0.1 \ -r requirements.txt -r requirements-dev.txt
正在生成什么
选项 -V 告诉 pypi2nix 使用哪个 Python 版本。要查看哪些 Python 版本可用,请运行 pypi2nix --help。
生成 Nix 表达式后,您应该能看到 3 个新文件
requirements_frozen.txt - 对您的 pypi2nix 调用的完整冻结集。这是您从 pip freeze 预期得到的输出。
requirements.nix 是一个包含构建的软件包集的 Nix 表达式的文件。
requirements_override.nix - 这是一个空文件,允许您覆盖生成的 Nix 表达式。
构建生成的包
构建单个软件包
% nix build -f requirements.nix packages.empy
构建所有软件包
% nix build -f requirements.nix packages
构建包含所有软件包的 Python 解释器
% nix build -f requirements.nix interpreter % ./result/bin/python -c "import empy"
进入开发环境
% nix run -f requirements.nix interpreter [user@localhost:~/dev/nixos/pypi2nix) % python -c "import empy"
使用生成的包
如果您正在处理一个其依赖项在 requirements.txt 中定义的项目,则可以创建一个 default.nix 并将生成的软件包添加为 buildInputs,如下所示
{}: let python = import ./requirements.nix { inherit pkgs; }; in python.mkDerivation { name = "ProjectA-1.0.0"; src = ./.; buildInputs = [ python.packages."coverage" python.packages."flake8" python.packages."mock" python.packages."pytest" python.packages."pytest-asyncio" python.packages."pytest-cov" python.packages."pytest-mock" python.packages."pytest-xdist" python.packages."virtualenv" ]; propagatedBuildInputs = [ python.packages."aiohttp" python.packages."arrow" python.packages."defusedxml" python.packages."frozendict" python.packages."jsonschema" python.packages."taskcluster" python.packages."virtualenv" ]; ... }
如您所见,您可以通过 python.packages."<name>" 访问所有软件包。如果您想要依赖所有软件包,甚至可以这样做
propagatedBuildInputs = builtins.attrValues python.packages;
命令行选项
- -v
增加输出给用户的信息量和详细信息。详细程度依次为 ERROR、WARNING、INFO 和 DEBUG。默认详细程度为 INFO。
- -q
减少输出给用户的信息量和详细信息。有关更多信息,请参阅 -v。
- -I/--nix-path TEXT
以类似 -I 与 nix 可执行文件(如 nix-build)的方式将条目添加到 NIX_PATH 环境变量中。这可以用于根据本地系统中使用的不同版本的 nixpkgs 生成包集。
- --nix-shell PATH
替代版本 nix-shell 命令的路径。默认是系统当前 PATH 中找到的第一个可执行文件。
- --version
显示 pypi2nix 的当前版本
- --basename TEXT
此选项确定生成的文件名。因此,使用 --basename environment 将得到 environment.nix、environment_frozen.nix 和 environment_override.nix 等文件。
- --extra-build-inputs/-E TEXT
额外的构建输入,这是必需的 Python 包需要运行的,例如 libffi 或 libgl。在这种情况下,您将提供 -E "libffi libgl"。这些 nix 包将在构建环境中的 wheel 中可用。
- --emit-extra-build-inputs/--no-emit-extra-build-inputs
这些选项让您控制通过 -E 指定的外部构建依赖是否最终会出现在生成的 nix 包集中。请注意,如果您选择此选项,您需要确保 Python 包找到它们各自的外部依赖。
- --extra-env/-N TEXT
传递给构建环境的额外环境变量。注意,您可以使用 nix 表达式在此字符串中,例如 -N 'BERKELEYDB_DIR=${pkgs.db.dev}'。
- --enable-tests/-T
如果您想启用生成 nix 表达式中的所有包的检查阶段,请指定此标志。请注意,此功能非常实验性,可能不会适用于您的用例。
- --python-version/-V
指定您希望要求集使用构建的 Python 版本。默认为 3,对应于 nixpkgs 的 python3 衍生。
- --requirements/-r FILE
指定一个要求文件,类似于您使用 pip 时的方法。pypi2nix 尝试与 pip 的文件格式完全兼容。
- --editable/-e TEXT
此选项允许您指定要添加到要求集中的单个要求,例如 pypi2nix -e attrs、pypi2nix -e $HOME/src/myproject#egg=myproject 或 pypi2nix -e .#egg=myegg。
- --setup-requires/-s TEXT
允许您指定需要存在于其他包构建环境中的 Python 包,一个好的例子是 setuptools-scm。请注意,pypi2nix 尝试自己检测这些依赖关系。您只需在包作者或维护者忘记在其设置中提及构建时依赖关系,或者既没有使用 setup.cfg 也没有使用 pyproject.toml 的情况下指定此标志。
- --overrides/-O URL
允许您指定符合 requirements_override.nix 通用结构的额外覆盖。我们支持带有 http 和 https 方案的常规 URL,以及 git。使用 https 的示例是:pypi2nix -O https://myoverrides.test/overrides.nix。从 Git 仓库重用覆盖层的方法如下:pypi2nix -O git+https://github.com/nix-community/pypi2nix.git&path=requirement_override.nix。请注意,这些覆盖将被纳入具有预先计算的哈希值的 nix 表达式中。因此,如果文件在上游发生更改,则无法再构建生成的软件包。
- --default-overrides/--no-default-overrides
从 https://github.com/nix-community/pypi2nix-overrides 拉取覆盖。此功能默认启用。
- --wheels-cache/-W TEXT
可以找到预构建 wheel 的位置。此选项最终将传递给 pip --find-links。请仅指向通过 pypi2nix 在您自己的或非常相似的系统上构建的 wheel。
- --build-directory TEXT
警告 pypi2nix 中的一个错误目前阻止某些软件包使用此选项进行构建。建议不要使用此标志。
将用于构建 Python 环境以生成所需 nix 表达式的目录。如果未指定,则构建目录将是临时的,并在程序退出前被删除。
3. 当它不起作用时
希望没有人期望 pypi2nix 总是做得完美。在 Python 打包中,有太多不同的案例,我们永远无法涵盖。pypi2nix 尝试做的是让您非常接近。
有时 pypi2nix 完全失败。如果发生这种情况,请打开一个错误报告——这几乎总是 pypi2nix 中的一个错误。然而,有时 pypi2nix 成功,但生成的 requirements.nix 文件在构建您的 Python 软件包时失败。根据问题的性质,本节可能有所帮助。
非Python/系统依赖项
相当多的 Python 软件包需要在构建时存在非 Python 依赖项。这些软件包将无法构建,并显示无法找到 foo.h 或某些 fooconfig 文件的错误消息。为了解决这个问题,pypi2nix 有 -E 选项,可以用于包含额外的非 Python 依赖项。
例如,psycopg2 需要 pg_config 二进制文件在安装时存在
% pypi2nix -v -V 2.7 -e psycopg2 -E postgresql
lxml 需要 libxml2 和 libxslt 系统软件包
% pypi2nix -v -V 2.7 -e lxml -E libxml2 -E libxslt
额外的环境变量
某些软件包期望设置额外的环境变量
% pypi2nix -v -V 2.7 -e bsddb3 -N 'BERKELEYDB_DIR=${pkgs.db.dev}'
使用 requirements_override.nix
一些其他失败可能是因为 pypi2nix 编写的导出不完全。一个非常常见的情况是,pypi2nix 未包括某些软件包的所有依赖项。例如,execnet 依赖于 setuptools-scm,但 pypi2nix 可能无法检测到这一点。
当发生这种情况时,Nix 将无法构建 execnet,可能还会收到来自 distutils/setuptools 的错误消息,抱怨找不到 setuptools-scm 的发行版。这里发生的情况是,通常 execnet 会从 PyPI 获取 setuptools-scm,但 Nix 禁用了网络访问以保证可重现性。因此,当您构建 execnet 时,它将无法找到 setuptools-scm。
对于这些情况,pypi2nix 提供了一个 requirements_override.nix 文件,允许您覆盖它生成的任何内容。您甚至可以通过这种方式添加新的软件包到依赖集合中。
例如,让我们将 setuptools-scm 添加为 execnet 的构建时依赖项。以下是 requirements_override.nix
{ pkgs, python }: self: super: { "execnet" = python.overrideDerivation super."execnet" (old: { buildInputs = old.buildInputs ++ [ self."setuptools-scm" ]; }); }
以类似的方式,您可以添加或删除任何 Python 软件包。
4. 高级使用
为您的项目创建 default.nix
没有什么比例子更能说明问题了
{ }: let pkgs = import <nixpkgs> {}; python = import ./requirements.nix { inherit pkgs; }; in python.mkDerivation { name = "projectA-1.0.0"; src = ./.; buildInputs = [ python.packages."coverage" python.packages."flake8" python.packages."mock" python.packages."pytest" python.packages."pytest-asyncio" python.packages."pytest-cov" python.packages."pytest-mock" python.packages."pytest-xdist" ]; propagatedBuildInputs = [ python.packages."aiohttp" python.packages."arrow" python.packages."defusedxml" python.packages."frozendict" python.packages."jsonschema" ]; checkPhase = '' export NO_TESTS_OVER_WIRE=1 export PYTHONDONTWRITEBYTECODE=1 flake8 src/ py.test --cov=src -cov-report term-missing coverage html ''; }
重要的是要知道,您将所有生成的软件包实例化为 python = import ./requirements.nix { inherit pkgs; };,这为您提供了一个包含 pypi2nix 生成的所有软件包以及一些常用工具的 Python 环境。
要创建软件包,您使用 python.mkDerivation,它类似于 nixpkgs 中的 pythonPackages.buildPythonPackage 函数。所有生成的软件包都作为 python.packages 下的一个属性集合可用。
pypi2nix 项目的未来目标之一是改进 nixpkgs 中 Python 工具的 UX。虽然这在 nixpkgs 中非常困难,但几乎在 nixpkgs 之外进行实验几乎是微不足道的。
将生成的 requirements.nix 转换为 nixpkgs 混合层
一个好的例子胜过千言万语。
overlay.nix
self: super: { customPython = (import ./requirements.nix { pkgs = self; }); }
shell.nix
with (import <nixpkgs> { overlays = [ (import ./overlay.nix) ]; }); customPython.interpreter
5. 帮助开发 pypi2nix
克隆 pypi2nix 仓库,并使用 nix-shell 命令进入开发环境。
% git clone https://github.com/nix-community/pypi2nix % cd pypi2nix % nix-shell
代码位于 src/pypi2nix。
测试
Pypi2nix 包含两种测试:单元测试和集成测试。它们分别位于 /unittests 和 /integrationtests 文件夹中。
单元测试非常直接。它们通过 pytest 运行,并尝试遵循 pytest 最佳实践。理想情况下,pypi2nix 的所有代码都应通过单元测试。如果可能,单元测试不应上网并从互联网获取数据。如果无法避免,请使用 @nix 装饰器(在 unittests.switches 中找到)标记需要网络访问的测试。
集成测试
集成测试稍微复杂一些。我们实现了一个小型框架来编写新测试并维护旧测试。有关编写自定义集成测试的信息,请查看 integrationtests.framework。要从 scripts 目录运行所有集成测试,请运行 run_integration_tests.py。如果您使用 nix-shell 创建开发环境,则 scripts 目录应包含在您的 PATH 变量中。
请注意,所有集成测试用例都是继承自 integrationtests.framework.IntegrationTest 的类。此外,所有这些测试都必须以 TestCase 结尾,例如 MyCustomTestCase。
维护脚本
scripts 文件夹包含帮助维护仓库的程序。我们期望用户已安装了 pypi2nix 构建环境中的所有软件包。如果用户选择在项目的顶级目录中进入 nix-shell,我们将 scripts 目录注册到用户的 PATH。
版本升级
我们使用 bumpv 来管理此项目的当前版本。此程序应该是开发环境的一部分。
项目详细信息
下载文件
下载适合您平台的应用程序。如果您不确定选择哪一个,请了解更多关于 安装软件包 的信息。
源代码分发
构建分发
pypi2nix-2.0.4.tar.gz 的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | 0df899d737f565347eb5affd769ab22dbcacbd014119891a64b07c19d99c9f78 |
|
MD5 | 55241c58ab838445305397a4aced0faa |
|
BLAKE2b-256 | 05764acabae987c7f3c8c86cf558bc91245f5c2804e63c29c00b5bcc6ad773d9 |
pypi2nix-2.0.4-py3-none-any.whl的哈希值
算法 | 散列摘要 | |
---|---|---|
SHA256 | 8952549f6669e3d5a8a62b5360480a3747400a4004277a1bb4bd89dd42bb399b |
|
MD5 | cda0e59c3f6abd91c1eec9d6fcadab2c |
|
BLAKE2b-256 | 4efded9b8bed69bb30e09c903d87799e4aca49ad7fc8fcc765b1f9eed9402340 |