Pipenv 的高级用法 — pipenv 文档

来自菜鸟教程
Pipenv/docs/v2020.11.15/advanced
跳转至:导航、​搜索

Pipenv 的高级用法

https://farm4.staticflickr.com/3672/33231486560_bff4124c9a_k_d.jpg 本文档涵盖了 Pipenv 的一些更辉煌和高级的功能。

☤ 注意事项

  • Pipfile 中提供的轮子的相关性不会被 $ pipenv lock 捕获。
  • 使用私有索引存在一些与散列相关的已知问题。 我们正在积极努力解决这个问题。 但是,您可能会很幸运。
  • 安装旨在尽可能确定性 - 如果遇到问题,请使用 --sequential 标志来增加这一点。


☤ 指定包索引

如果您希望使用特定软件包索引安装特定软件包,您可以执行以下操作:

[[../source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[[../source]]
url = "http://pypi.home.kennethreitz.org/simple"
verify_ssl = false
name = "home"

[dev-packages]

[packages]
requests = {version="*", index="home"}
maya = {version="*", index="pypi"}
records = "*"

很花哨。


☤ 使用 PyPI 镜像

如果你想用 PyPI 镜像的 URL 覆盖默认的 PyPI 索引 URL,你可以使用以下命令:

$ pipenv install --pypi-mirror <mirror_url>

$ pipenv update --pypi-mirror <mirror_url>

$ pipenv sync --pypi-mirror <mirror_url>

$ pipenv lock --pypi-mirror <mirror_url>

$ pipenv uninstall --pypi-mirror <mirror_url>

或者,您可以设置 PIPENV_PYPI_MIRROR 环境变量。


☤ 通过环境变量将凭据注入 Pipfiles

Pipenv 将在您的 Pipfile 中扩展环境变量(如果已定义)。 如果您需要对私有 PyPI 进行身份验证,则非常有用:

[[../source]]
url = "https://$USERNAME:${PASSWORD}@mypypi.example.com/simple"
verify_ssl = true
name = "pypi"

幸运的是 - pipenv 将在 扩展环境变量之前散列您的 Pipfile (并且,当您从锁定文件安装时,将再次替换环境变量,因此无需提交任何秘密! 呜!)

如果您的凭据包含特殊字符,请用引号将环境变量的引用括起来。 例如,如果您的密码包含双引号,请用单引号将密码变量括起来。 否则,在安装依赖项时可能会出现 ValueError, "No closing quotation" 错误。

[[../source]]
url = "https://$USERNAME:'${PASSWORD}'@mypypi.example.com/simple"

环境变量可以指定为 ${MY_ENVAR}$MY_ENVAR

在 Windows 上,除了 ${MY_ENVAR}$MY_ENVAR 之外,还支持 %MY_ENVAR%

需求说明符URL部分的环境变量也可以扩展,其中变量必须是${VAR_NAME}的形式。 $VAR_NAME%VAR_NAME% 都不可接受:

[[../package]]
requests = {git = "git://${USERNAME}:${PASSWORD}@private.git.com/psf/requests.git", ref = "2.22.0"}

请记住,环境变量在运行时被扩展,PipfilePipfile.lock 中的条目保持不变。 这是为了避免源代码中凭据的意外泄漏。


☤ 基本上什么都指定

如果你想指定一个特定的包只安装在某些系统上,你可以使用 PEP 508 说明符 来完成这个。

下面是一个例子Pipfile,它只会在Windows系统上安装pywinusb

[[../source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"

[packages]
requests = "*"
pywinusb = {version = "*", sys_platform = "== 'win32'"}

瞧!

这是一个更复杂的例子:

[[../source]]
url = "https://pypi.python.org/simple"
verify_ssl = true

[packages]
unittest2 = {version = ">=1.0,<3.0", markers="python_version < '2.7.9' or (python_version >= '3.0' and python_version < '3.4')"}

魔法。 纯粹的魔法。


☤ 使用 pipenv 进行部署

您可能希望使用 pipenv 作为部署过程的一部分。

您可以使用 --deploy 标志强制您的 Pipfile.lock 是最新的:

$ pipenv install --deploy

如果 Pipfile.lock 已过时,而不是生成新的,这将使构建失败。

或者,您可以使用 sync 命令完全按照 Pipfile.lock 中指定的方式安装软件包:

$ pipenv sync

笔记

pipenv install --ignore-pipfile 几乎等同于 pipenv sync,但 pipenv sync永远不会 尝试重新锁定您的依赖项,因为它被视为原子操作。 pipenv install 默认会尝试重新锁定,除非使用 --deploy 标志。


部署系统依赖

您可以使用 --system 标志告诉 Pipenv 将 Pipfile 的内容安装到其父系统中:

$ pipenv install --system

这对于管理系统 Python 和部署基础设施(例如 Heroku 这样做)。


☤ Pipenv 和其他 Python 发行版

将 Pipenv 与第三方 Python 发行版(例如 Anaconda),您只需提供 Python 二进制文件的路径:

$ pipenv install --python=/path/to/python

Anaconda 使用 Conda 来管理包。 要重用 Conda 安装的 Python 包,请使用 --site-packages 标志:

$ pipenv --python=/path/to/python --site-packages

☤ 生成requirements.txt

您可以非常轻松地将 PipfilePipfile.lock 转换为 requirements.txt 文件,并获得我们包含的附加功能和其他好处的所有好处。

我们拿这个Pipfile

[[../source]]
url = "https://pypi.python.org/simple"
verify_ssl = true

[packages]
requests = {version="*"}

[dev-packages]
pytest = {version="*"}

并仅使用默认依赖项生成一组需求:

$ pipenv lock -r
chardet==3.0.4
requests==2.18.4
certifi==2017.7.27.1
idna==2.6
urllib3==1.22

与其他命令一样,传递 --dev 将包括默认和开发依赖项:

$ pipenv lock -r --dev
chardet==3.0.4
requests==2.18.4
certifi==2017.7.27.1
idna==2.6
urllib3==1.22
py==1.4.34
pytest==3.2.3

最后,如果您希望生成仅包含开发需求的需求文件,您也可以使用 --dev-only 标志:

$ pipenv lock -r --dev-only
py==1.4.34
pytest==3.2.3

锁定的需求被写入标准输出,使用 shell 输出重定向将它们写入文件:

$ pipenv lock -r > requirements.txt
$ pipenv lock -r --dev-only > dev-requirements.txt
$ cat requirements.txt
chardet==3.0.4
requests==2.18.4
certifi==2017.7.27.1
idna==2.6
urllib3==1.22
$ cat dev-requirements.txt
py==1.4.34
pytest==3.2.3

☤ 安全漏洞检测

Pipenv 包含 safety 包,并将使用它来扫描您的依赖图以查找已知的安全漏洞!

例子:

$ cat Pipfile
[packages]
django = "==1.10.1"

$ pipenv check
Checking PEP 508 requirements...
Passed!
Checking installed package safety...

33075: django >=1.10,<1.10.3 resolved (1.10.1 installed)!
Django before 1.8.x before 1.8.16, 1.9.x before 1.9.11, and 1.10.x before 1.10.3, when settings.DEBUG is True, allow remote attackers to conduct DNS rebinding attacks by leveraging failure to validate the HTTP Host header against settings.ALLOWED_HOSTS.

33076: django >=1.10,<1.10.3 resolved (1.10.1 installed)!
Django 1.8.x before 1.8.16, 1.9.x before 1.9.11, and 1.10.x before 1.10.3 use a hardcoded password for a temporary database user created when running tests with an Oracle database, which makes it easier for remote attackers to obtain access to the database server by leveraging failure to manually specify a password in the database settings TEST dictionary.

33300: django >=1.10,<1.10.7 resolved (1.10.1 installed)!
CVE-2017-7233: Open redirect and possible XSS attack via user-supplied numeric redirect URLs
============================================================================================

Django relies on user input in some cases  (e.g.
:func:`django.contrib.auth.views.login` and :doc:`i18n </topics/i18n/index>`)
to redirect the user to an "on success" URL. The security check for these
redirects (namely ``django.utils.http.is_safe_url()``) considered some numeric
URLs (e.g. ``http:999999999``) "safe" when they shouldn't be.

Also, if a developer relies on ``is_safe_url()`` to provide safe redirect
targets and puts such a URL into a link, they could suffer from an XSS attack.

CVE-2017-7234: Open redirect vulnerability in ``django.views.static.serve()``
=============================================================================

A maliciously crafted URL to a Django site using the
:func:`~django.views.static.serve` view could redirect to any other domain. The
view no longer does any redirects as they don't provide any known, useful
functionality.

Note, however, that this view has always carried a warning that it is not
hardened for production use and should be used only as a development aid.

✨🍰✨

笔记

每个月,PyUp.io 更新不安全 Python 包的 safety 数据库,并 将其免费提供给社区 。 Pipenv 会调用 API 来检索这些结果,并在您每次运行 pipenv check 时使用它们来向您展示易受攻击的依赖项。

更多最新的漏洞数据,您也可以通过设置环境变量PIPENV_PYUP_API_KEY来使用自己的安全API密钥。


☤ 社区整合

有一系列社区维护的插件和扩展可用于一系列编辑器和 IDE,以及与 Pipenv 项目集成的不同产品:

正在进行的工作:

  • Sublime Text(编辑器集成)
  • 神秘即将推出的谷歌云产品(云托管)


☤ 在你的编辑器中打开一个模块

Pipenv 允许您使用 $ pipenv open 命令打开任何已安装的 Python 模块(包括代码库中的模块):

$ pipenv install -e git+https://github.com/kennethreitz/background.git#egg=background
Installing -e git+https://github.com/kennethreitz/background.git#egg=background...
...
Updated Pipfile.lock!

$ pipenv open background
Opening '/Users/kennethreitz/.local/share/virtualenvs/hmm-mGOawwm_/src/background/background.py' in your EDITOR.

这使您可以轻松阅读正在使用的代码,而不是在 GitHub 上查找。

笔记

为此使用标准的 EDITOR 环境变量。 例如,如果您使用 VS Code,您需要 export EDITOR=code(如果您使用的是 macOS,您需要 将命令 安装到 PATH ] 第一的)。


☤ 自动安装Python

如果你已经安装并配置了 pyenv,Pipenv 会自动询问你是否想要安装所需的 Python 版本,如果你还没有的话。

这是一个非常奇特的功能,我们为此感到非常自豪:

$ cat Pipfile
[[../source]]
url = "https://pypi.python.org/simple"
verify_ssl = true

[dev-packages]

[packages]
requests = "*"

[requires]
python_version = "3.6"

$ pipenv install
Warning: Python 3.6 was not found on your system...
Would you like us to install latest CPython 3.6 with pyenv? [Y/n]: y
Installing CPython 3.6.2 with pyenv (this may take a few minutes)...
...
Making Python installation global...
Creating a virtualenv for this project...
Using /Users/kennethreitz/.pyenv/shims/python3 to create virtualenv...
...
No package provided, installing all dependencies.
...
Installing dependencies from Pipfile.lock...
🐍   ❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒❒ 5/5 — 00:00:03
To activate this project's virtualenv, run the following:
 $ pipenv shell

Pipenv 自动支持 [X37X] 和 python_version PEP 508 说明符。

💫✨🍰✨💫


☤ 自动加载.env

如果您的项目中存在 .env 文件,$ pipenv shell$ pipenv run 将自动加载它,为您:

$ cat .env
HELLO=WORLD⏎

$ pipenv run python
Loading .env environment variables...
Python 2.7.13 (default, Jul 18 2017, 09:17:00)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ['HELLO']
'WORLD'

使用 ${VARNAME} 语法在 .env 文件中可以使用类似 Shell 的变量扩展。:

$ cat .env
CONFIG_PATH=${HOME}/.config/foo

$ pipenv run python
Loading .env environment variables...
Python 3.7.6 (default, Dec 19 2019, 22:52:49)
[GCC 9.2.1 20190827 (Red Hat 9.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ['CONFIG_PATH']
'/home/kennethreitz/.config/foo'

这对于将生产凭据保留在代码库之外非常有用。 我们不建议将 .env 文件提交到源代码管理中!

如果您的 .env 文件位于不同的路径或具有不同的名称,您可以设置 PIPENV_DOTENV_LOCATION 环境变量:

$ PIPENV_DOTENV_LOCATION=/path/to/.env pipenv shell

要防止 pipenv 加载 .env 文件,请设置 PIPENV_DONT_LOAD_ENV 环境变量:

$ PIPENV_DONT_LOAD_ENV=1 pipenv shell

有关 .env 文件的更多信息,请参阅 theskumar/python-dotenv


☤ 自定义脚本快捷键

Pipenv 支持在 Pipfile 的(可选)[scripts] 部分创建自定义快捷方式。

然后,您可以在终端中运行 pipenv run <shortcut name> 以在 pipenv 虚拟环境的上下文中运行命令,即使您没有先激活 pipenv shell。

例如,在您的 Pipfile 中:

[scripts]
printspam = "python -c \"print('I am a silly example, no one would need to do this')\""

然后在您的终端中:

$ pipenv run printspam
I am a silly example, no one would need to do this

需要参数的命令也可以使用。 例如:

[scripts]
echospam = "echo I am really a very silly example"
$ pipenv run echospam "indeed"
I am really a very silly example indeed

然后,您可以通过在终端中运行 pipenv scripts 来显示快捷方式的名称和命令。

$ pipenv scripts
command   script
echospam  echo I am really a very silly example

☤ 配置环境变量

Pipenv 带有一些可以通过 shell 环境变量启用的选项。 要激活它们,只需在 shell 中创建变量,pipenv 就会检测到它。

如果您想在每个项目的基础上设置这些环境变量,我建议使用出色的 direnv 项目,以便这样做。

另请注意,pip 本身支持环境变量,如果您需要额外的自定义。

例如:

$ PIP_INSTALL_OPTION="-- -DCMAKE_BUILD_TYPE=Release" pipenv install -e .

☤ 自定义虚拟环境位置

Pipenv 自动遵守 WORKON_HOME 环境变量,如果你设置了它——所以你可以告诉 pipenv 将你的虚拟环境存储在你想要的任何地方,例如:

export WORKON_HOME=~/.venvs

此外,您还可以通过设置 PIPENV_VENV_IN_PROJECT 环境变量,让 Pipenv 将 virtualenv 粘贴到 project/.venv 中。


☤ 测试项目

Pipenv 被用于 Requests 等项目中,用于声明开发依赖项和运行测试套件。

我们目前已经成功测试了 Travis-CItox 的部署。

特拉维斯·CI

可以在 Requests 中找到 Travis CI 设置示例。 该项目使用 Makefile 来定义常用函数,例如其 inittests 命令。 这是一个精简的示例 .travis.yml

language: python
python:
    - "2.6"
    - "2.7"
    - "3.3"
    - "3.4"
    - "3.5"
    - "3.6"
    - "3.7-dev"

# command to install dependencies
install: "make"

# command to run tests
script:
    - make test

和相应的Makefile:

init:
    pip install pipenv
    pipenv install --dev

test:
    pipenv run pytest tests

毒物自动化项目

或者,您可以为本地和外部测试配置如下所示的 tox.ini

[tox]
envlist = flake8-py3, py26, py27, py33, py34, py35, py36, pypy

[testenv]
deps = pipenv
commands=
    pipenv install --dev
    pipenv run pytest tests

[testenv:flake8-py3]
basepython = python3.4
commands=
    pipenv install --dev
    pipenv run flake8 --version
    pipenv run flake8 setup.py docs project test

Pipenv 会自动使用 tox 提供的 virtualenv。 如果 pipenv install --dev 安装例如 pytest,然后安装的命令 pytest 将出现在给定的 virtualenv 中,可以直接由 pytest tests 而不是 pipenv run pytest tests 调用。

您可能还想将 --ignore-pipfile 添加到 pipenv install,以免在每次测试运行时意外修改锁定文件。 这会导致 Pipenv 忽略对 Pipfile 的更改,并且(更重要的是)阻止其将当前环境添加到 Pipfile.lock。 这可能很重要,因为当前环境(即 由 tox 提供的 virtualenv)通常包含当前项目(可能需要也可能不需要)和来自 toxdeps 指令的附加依赖项。 也可以通过将 skip_install = True 添加到 tox.ini 来禁用初始配置。

此方法要求您明确更新锁定文件,这在任何情况下都可能是一个好主意。

第 3 方插件 tox-pipenv 也可用于在本地使用 Pipenv 和 tox。


☤ 壳完成

要在 fish 中启用完成,请将其添加到您的配置中:

eval (pipenv --completion)

或者,使用 bash 或 zsh,将其添加到您的配置中:

eval "$(pipenv --completion)"

魔法外壳补全功能现已启用!

✨🍰✨


☤ 使用平台提供的 Python 组件

操作系统接口的平台特定 Python 绑定只能通过系统包管理器使用是相当普遍的,因此无法通过 pip 安装到虚拟环境中。 在这些情况下,可以通过访问系统 site-packages 目录来创建虚拟环境:

$ pipenv --three --site-packages

为确保所有 pip 可安装组件实际安装到虚拟环境中,并且系统包仅用于根本不参与 Python 级依赖项解析的接口,请使用 PIP_IGNORE_INSTALLED[ X257X] 设置:

$ PIP_IGNORE_INSTALLED=1 pipenv install --dev

☤ Pipfile 与 setup.py

应用程序之间有一个微妙但非常重要的区别。 这是 Python 社区中一个非常常见的混淆来源。

库为其他库和应用程序提供可重用的功能(让我们在这里使用总称 projects)。 他们需要与其他库一起工作,所有库都有自己的子依赖集。 他们定义了抽象依赖。 为避免项目中不同库的子依赖项中的版本冲突,库永远不应该固定依赖项版本。 尽管他们可能会指定下限或(不太频繁)上限,但如果他们依赖于某些特定的功能/修复/错误。 库依赖项通过 setup.py 中的 install_requires 指定。

库最终旨在用于某些 应用程序 。 应用程序的不同之处在于它们通常不依赖于其他项目。 它们旨在部署到某些特定环境中,只有这样才能使所有依赖项和子依赖项的确切版本变得具体。 使这个过程更容易是目前 Pipenv 的主要目标。

总结一下:

  • 对于库,通过setup.py中的install_requires定义抽象依赖。 确切地安装哪个版本以及从哪里获取该依赖项的决定不是您的决定!
  • 对于应用程序,在 Pipfile 中定义 依赖项以及从何处获取它们 ,并使用此文件更新 Pipfile.lock 中的 具体依赖项 集。 此文件定义了已知适用于您的项目的特定幂等环境。 Pipfile.lock 是您的真相来源。 Pipfile 方便您创建该锁定文件,因为它允许您对要使用的依赖项的确切版本仍然有些模糊。 Pipenv 可以帮助您定义一组无冲突的特定依赖版本,否则这将是一项非常乏味的任务。
  • 当然,Pipfile 和 Pipenv 对库开发人员仍然有用,因为它们可用于定义开发或测试环境。
  • 而且,当然,有些项目的库和应用程序之间的区别不是那么清楚。 在这种情况下,将 install_requires 与 Pipenv 和 Pipfile 一起使用。

你也可以这样做:

$ pipenv install -e .

这将告诉 Pipenv 锁定所有 setup.py 声明的依赖项。


☤ 改变 Pipenv 的缓存位置

您可以通过将环境变量 PIPENV_CACHE_DIR 设置为您希望的位置来强制 Pipenv 使用不同的缓存位置。 这在将 PIP_CACHE_DIR 更改为不同目录的相同情况下很有用。


☤ 更改默认 Python 版本

默认情况下,Pipenv 将使用 python3 的任何版本的 python 初始化项目。 除了使用 --three--two 标志启动项目,您还可以使用 PIPENV_DEFAULT_PYTHON_VERSION 指定在 --three 或 [ X166X] 未使用。