Pipenv: 仅更新一个锁定的依赖项

创建于 2017-10-24  ·  82评论  ·  资料来源: pypa/pipenv

有时我在做PR,我想更新特定的依赖项,但不想处理所有依赖项的更新(aiohttp,flake8等)。 如果在这些依赖项中引入了任何重大更改,我想在另一个PR中进行处理。

据我所知,唯一的方法就是将所有我不想更新的依赖项固定在Pipfile中。 但是我发现它首先打败了Pipenv的目的:)。

因此,我的功能要求是能够执行以下操作:

$ pipenv lock --only my-awesome-dep

这将生成一个仅更新my-awesome-dep及其依赖项的Pipfile.lock。

我可能可以为此做一个公关,但我想先获得一些反馈。

最有用的评论

同意100%-我会说得更远:这应该是默认设置。

也就是说,除了foo及其依赖项之外, pipenv install foo绝不能碰任何东西。 pipenv lock当然应该永远不要升级任何东西-它应该锁定已安装的内容。

AFAICT,这就是npmyarngem等的工作方式; 拥有一个实际上没有锁定软件包的锁文件是没有意义的,但是要让软件包作者相信不要破坏补丁程序发行版中的内容,因此可以在不被要求的情况下对其进行升级。 我可以看到允许升级的用法,但是应该选择启用,因为比不升级它们更令人惊讶。

如果我要劫持其他问题,我深表歉意,但是由于这与我将要创建的问题密切相关,因此我认为我将在这里开始讨论。 随时告诉我,我应该再做一个。

所有82条评论

这对于pipenv install也可能很有用,因为有时我想安装新的依赖项而不更新其他依赖项。

这里有一点要考虑的事项:更改单个依赖项可能会更改总体要求。
例如:将foo从1.0更新到2.0可能需要将bar更新

我知道在pip-tools本身的上下文中( pipenv采取依赖关系解析算法),运行依赖关系解析只会在“重新锁定”时“更新”所需的程序包,如果存在现有的锁定文件。 通过在解析中选择候选对象时,首先检查锁定文件中现有的引脚是否为有效候选对象,以实现此目的。 pipenv可能会做同样的事情。

我认为这是一个合理的想法。 否则,如果您只想绝对更新一个依赖项,则如果更改依赖项导致其他更改,则pipenv必须具有一种阻止模式,否则您将失去有效环境的保证。

我希望这有帮助!

实际上,这就是我的意思:

这将生成一个仅对my-awesome-dep及其依赖项进行更新的Pipfile.lock。

同意100%-我会说得更远:这应该是默认设置。

也就是说,除了foo及其依赖项之外, pipenv install foo绝不能碰任何东西。 pipenv lock当然应该永远不要升级任何东西-它应该锁定已安装的内容。

AFAICT,这就是npmyarngem等的工作方式; 拥有一个实际上没有锁定软件包的锁文件是没有意义的,但是要让软件包作者相信不要破坏补丁程序发行版中的内容,因此可以在不被要求的情况下对其进行升级。 我可以看到允许升级的用法,但是应该选择启用,因为比不升级它们更令人惊讶。

如果我要劫持其他问题,我深表歉意,但是由于这与我将要创建的问题密切相关,因此我认为我将在这里开始讨论。 随时告诉我,我应该再做一个。

刚刚也发现了这个相关问题: https :

能够指定pipenv install --upgrade-strategy=only-if-needed似乎是我正在寻找的东西,尽管正如我提到的那样,我当然认为它应该是默认值,因为它已成为第10点。但是可以通过永久指定它无论如何,env var会是某种东西。

如果该更改中断了任何人的工作流程(最著名的遗言),我会感到惊讶,因为它比--upgrade-strategy=eager更为保守。

尝试通过在我的shell配置中设置export PIP_UPGRADE_STRATEGY=only-if-needed来解决此问题。 这不起作用, pipenv lock表现出以下令人惊讶的行为:

  1. 它“升级”不需要升级的软件包(但是...)
  2. 实际上,它不会升级已安装的版本! 即pip freezePipfile.lock显示不同的版本!

Guessing pipenv将委派给pip进行安装,并且pip尊重其环境变量设置,但pipenv lock则不然。

@ k4nar您发现不受欢迎的东西现在会发生什么? 因为如果升级具有级联需求的依赖项,显然会对其他依赖项产生影响。 您是否建议某种解析程序逻辑来确定特定包的最新版本_在当前lockfile_的上下文中? 我很犹豫地鼓励对解析逻辑进行过多的修改,因为这些解析已经很复杂并且很难调试。

@brettdh我想我可以阐明一些pipenv lock不会安装任何东西,也不会声明安装任何东西。 仅在给定主机环境,python版本和提供的Pipfile ,它才会生成锁定文件。 如果您以其他方式操纵您的环境,或者您直接使用pip /在pipenv之外操作pip设置/未在pipenv子外壳中使用pipenv run或使用pip freeze ,则对于与pip freeze不同步的锁定文件。 两者并不真正相关。

要清楚:

  1. Pipfile.lock是严格固定的依赖项解析,使用pip-tools解析器基于用户的Pipfile
  2. 如果您想仅升级一个软件包就保持所有功能的严格固定,我相信您可以通过严格固定Pipfile所有功能来做到这一点,但您要升级的一件事除外(如果我错了,请纠正我@vphilippon)

至于你的锁文件和pip freeze彼此不同意,我不得不知道更多信息,但是我相信当使用非系统版本的python进行解析时,我们的锁文件解析器存在一个开放性问题。

@techalchemy :如果我有一个带有A,B和C的Pipfile.lock,其中B是A的依赖项,我希望能够不更新C而更新A和B,或者不更新A和B而更新C。
当然,我可以再次将所有依赖关系及其依赖关系固定在我的Pipfile中,以便这样做,但这将是一个负担(像大多数requirements.txt一样)。

我同意@ k4nar编写的所有内容。 当然,我什至可以别针
而不是使用pipenv中的所有内容。 pipenv的点是
拥有一个可以做到这一点的工具(当然还有virtualenv的东西)
更易于管理; 即所有软件包默认情况下都锁定为一个版本
可以正常工作,但是升级精选产品应该很简单
很少(不会意外升级其他)。
在星期四,2017年10月26日在上午04时28分亚尼克PÉROUX [email protected]
写道:

@techalchemy https://github.com/techalchemy :如果我有一个Pipfile.lock
与A,B和C(其中B是A的依赖项),我希望能够
在不更新C的情况下更新A和B,或在不更新A和B的情况下更新C。
当然,我可以再次将所有依赖项及其依赖项固定在我的
Pipfile才能做到这一点,但这将是维护的负担(例如
大多数requirements.txt是)。

-
您收到此邮件是因为有人提到您。
直接回复此电子邮件,在GitHub上查看
https://github.com/kennethreitz/pipenv/issues/966#issuecomment-339591307
或使线程静音
https://github.com/notifications/unsubscribe-auth/AAFlnqUOEKARiFD8kEk3GVczF3NXBdVOks5swEKcgaJpZM4QEf--

嗯,我明白你们在说什么。 将设置传递给pip的前提不是我担心的事情,它是通过与我有关的pip工具解决的。 此行为现​​在看起来像什么?

@techalchemy我提到pip freeze不同之处是“ pipenv install安装的软件包版本不同于pipenv lock保存到Pipfile.lock的软件包版本”。

没错,只有在我通过环境变量更改了pip的默认参数时,才会发生这种情况。 我只是指出,pipenv被委派给pip进行安装而不是版本锁定,这令人惊讶。 也就是说,它锁定了它认为应该安装的内容,而不是锁定已安装的内容,可能会进行不需要的升级。

您能澄清一下您的问题吗? 我认为“使用pip-tools解决”是指pipenv lock在做什么,以及当我设置pip默认值时不受影响的原因? 您能否更具体地说明“这种行为”的含义?

@brettdh锁定机制包括pip中不存在的“依赖关系解决方案”概念。 它由pip-tools (或更确切地说,是其修补版本,由pipenv以特殊方式集成,与原始工具有一些区别)。 简而言之,锁定机制读取Pipfile并执行完整的依赖项解析,以选择将满足所需包及其依赖项所定义的所有约束的整套程序包。

@techalchemy

[...]正在解决与我有关的pip工具。

我不确定这些--upgrade-strategypip-tools有何影响,因为它可以在pip一些低级内部使用。 我觉得这不会产生预期的结果,因为这些选项考虑了已安装的内容,而这并不是该机制要处理的内容。 但是我们可以在pip-tools中使用另一种方法来解决此问题。

“原始” pip-tools行为是,它仅更新锁定文件中需要的内容(在上下文中为requirements.txt),但这在解析器集成到pipenv中的方式“丢失”了

回到我关于pip-tools工作原理的简历: https :
还记得“选择候选人”部分吗? 这是通过查询Repository对象来完成的。
pipenv ,我们直接为Resolver配置PyPIRepository ,但是pip-tools做其他事情,它使用LocalRequirementsRepository对象,该对象保留先前存在的requirements.txt (如果找到)中的现有图钉,并保留PyPIRepository上的“后备”。

因此,在pip-tools ,选择候选人时会发生以下情况:

  1. 查询LocalRequirementsRepository匹配foobar>=1.0,<2.0的候选人。
  2. 检查现有的引脚是否满足该要求:

    • 如果是,则将该引脚作为候选引脚。

    • 如果不是,请向proxied_repositoryPyPIRepository )查询候选人。

  3. 使用返回的候选人

有效地,这意味着为现有的引脚提供“优先级”作为首先尝试的候选对象。

但目前在pipenv ,它只是:

  1. (直接)查询PyPIRepository匹配foobar>=1.0,<2.0的候选人。
  2. 使用返回的候选人。

因此,我认为可以通过解析Pipfile.lock以获取现有的引脚并使用LocalRequirementsRepository来完成锁定pipenv的相同行为,例如pip-tools在其pip-compile命令中执行。

@vphilippon您是否知道在此之上实施会有多困难?

@techalchemy

  • 解析Pipfile.lock以提取现有的图钉:没看过。 取决于pipenv事物的结构。 我们需要一组InstallRequirements来代表Pipfile.lock的引脚。
  • 使用LocalRequirementsRepository :非常简单:将当前的PyPIRepository更改为LocalRequirementsRepository

但是,当我调查此问题并遵循@brettdh注释时,我意识到一些事情:

  1. 当前的默认pipenv install行为与pipenv lock行为不匹配。 如果有新版本出现,则单独执行pipenv install requests不会更新requests (就像直接pip install )。 但是,执行pipenv lock将使用与Pipfile说明符匹配的最新版本requests和依赖关系约束来更新Pipfile.lock
    有两种主要的查看方式:

    • A) Pipfile.lock默认情况下应保持尽可能稳定,除非需要,否则不要更改引脚,以便像当前环境一样保持状态,并且仅在我们更改环境的情况下才进行更改。

    • B) Pipfile.lock应该获得尊重环境约束/依赖关系的最新版本,以便自由地从Pipfile和lib依赖关系的开放范围中受益,从而可以在Windows中连续获取新的兼容版本您的环境。 然后,您可以运行pipenv update以使用新的锁定。

IMHO, I would align the default behavior, which would be to go with A) by default. Because right now, everytime a lock is performed (i.e. after each installation), new versions can come in, which make the lockfile *drive the update of the environment*, which seems weird. But, this is arguable of course. While in development, I might want to continuously update my requirements to no get stale, like with B), so that should also be easily doable.
  1. 即使我们使用LocalRequirementsRepository来避免更新正确的现有管脚并最终对齐默认行为,我们也需要为锁定部分解决等效的--upgrade--upgrade-strategy 。 当前,定义一些环境变量(例如PIP_UPGRADEPIP_UPGRADE_STRATEGY )将影响pipenv install行为,但不会影响pipenv lock ,因为它不会影响pip-tools的行为(我一开始就不确定,所以我确认了这一点)。
    否则,没有删除Pipfile.lock (感觉笨拙,“全有或全无”)或需要更新版本(没有明确的pipenv install requests>2.18.4 ,就无法更新环境。这需要您知道有新版本发布,并更改Pipfile本身的说明符,增加下限),这是错误的。 由于“原始pip-tools ”不对应pip来处理此问题(因为与当前安装的内容无关),因此它提供了一个选项来指定要更新的依赖项锁定文件,只需从现存引脚列表中删除这些软件包(或全部)的引脚,即可有效地回退到查询PyPI。 我不确定如何将“ --upgrade-strategy”的概念与此相匹配。

@techalchemy
因此,尽管我说“对齐​​默认行为”相当容易,但我现在意识到这将导致一些重大问题,无法更新软件包(例如:仅获取符合我当前约束的最新版本) 。

如果有不清楚的地方,请问一下,编写此文件时需要进行大量编辑。

(依赖解决方案并不容易。好的且实用的依赖解决方案更糟糕😄)

@vphilippon就是我的意思。 使pip安装的内容与pip-tools解决的内容保持同步并非易事,除非您使用已解析的锁定文件来反向驱动进程,以进行安装。 我很确定这就是为什么要按原样设计事物的原因。

B)Pipfile.lock应该获得尊重环境约束/依赖性的最新版本,以便自由地从Pipfile和lib依赖性的开放范围中受益,从而可以在您的环境中连续获取新的兼容版本。 然后,您可以运行pipenv update以从新锁定中受益。

此工作流程可能可以使用当前配置。 您可以使用pipenv lock生成锁定文件,但是pipenv update将重新安装整个环境。 我很确定我们可以使用各种输出格式之一来解决依赖关系图(您已经知道,我们已经拥有json格式),并且只需重新安装与锁定文件不对齐的内容即可。 这可能更明智,但在做出决定之前,我会对@nateprewitt@erinxocon的输入感到好奇

@vphilippon完全同意A和B在不同情况下是理想的工作流程。 但是,您对B的某些表述使我有些困惑,似乎是在说pipenv lock可能导致一个锁文件实际上与环境不匹配-我特别听到这一点,因为它需要“运行pipenv update将从新锁中受益”-就像锁在环境的“前面”而不是与之匹配。

无论您是在A工作流程中还是在B工作流程中,对我来说,都有几件事是不变的,我认为这也与@techalchemy所说的相吻合:

  • pipenv lock应始终是与环境匹配的锁文件。
  • pipenv install应始终是与锁定文件匹配的环境。

我忽略了实现细节,但这只是我期望具有锁定文件功能的软件包管理器的基本行为。

定期运行pipenv update可以让您一直处于B模式,只要您希望一切都新鲜,而具有pipenv install --upgrade requests将允许对一个软件包及其依赖项进行特定的更新,而不会影响软件包不需要不必要的升级。

我是否缺少任何用例? 我可以想到B的优化-例如,标志或env var告诉它总是不断更新-但我认为这涵盖了基础知识。 我也知道我正在重读您已经介绍过的内容; 确保我了解您的意思对我很有帮助。 :)

但是,您对B的某些表述使我有些困惑,似乎是在说pipenv锁定可能会导致实际上不匹配环境的锁定文件

@brettdh这是正确的-我们用来生成Pipfile.lockpip-tools解析器不会向virtualenv询问已安装软件包的列表。 而是从Pipfile编译满足引脚列表中指定条件的软件包列表。 由于解析器本身是使用系统运行的,也可以使用外部python / pipenv / pip-tools安装程序运行,因此我们正在做一些极端的事情,以说服它使用virtualenv中使用的相同版本的python解析软件包。 假设pip install可以类似地解决问题,但这并非总是如此,尽管即使我对此也不确定100%。 但是,是的, pipenv lock不是基于virtualenv生成的,而是基于Pipfile 。 它是一个依赖关系解决方案锁定文件,而不是环境状态引脚。

作为对此的潜在解决方案:约束文件的概念是pip本身当前支持但pip-compile不支持的某种东西。

约束文件与需求文件的不同之处在于:“如果安装了此组件,则它必须满足此版本约束”。 但是,如果约束文件中的特定程序包未显示在依赖关系树中的任何位置,则不会将其添加到要安装的程序包集中。

pipenv目前缺少此功能,因为向Pipfile.lock生成的所需输入为:

  1. 更新后的Pipfile内容作为新的需求输入文件
  2. Pipfile.lock中所有现有依赖项的完整集合,作为约束文件,不包括在当前命令中专门命名的软件包

然后,在pip-tools解析程序级别上对约束文件的支持就足以让pipenv支持一种模式,在这种模式下,尝试进行依赖项的隐式升级会因为违反约束而失败,从而使用户可以决定是否要添加该软件包到正在更新的集合。

当前不支持,感谢您的反馈

@kennethreitz

你的意思是:

  1. 此行为应更改,但当前不是优先事项,
  2. 应该将此行为添加为可选行为,但当前不是优先事项,或者
  3. 这种行为不应该添加吗?

考虑到与其他类似的锁定程序包管理器的工作方式不一致,这是一个足够的不便之处,因此最好还是将其保持为公开状态以吸引PR。

如果改为(3),并且不会添加,那么我认为在此问题上的许多人将需要针对我们选择的Python包管理工具调整计划。

我的意思是当前不支持此功能,感谢您的反馈。

我了解不支持此功能。 您是否还说您不接受更改此行为或将其添加为选项的PR?

我不知道。

@ k4nar仍然对此有兴趣进行PR? 具体来说,像pipenv install --only <dep-to-update这样的东西可以防止无关的deps被更新。 由于@kennethreitz似乎对进一步讨论不感兴趣,因此在我看来,这是找出行为增加/改变是否可以接受的唯一方法(以及扩展地,像@taion这样的人和我是否可以继续使用pipenv)。

我很感兴趣,但是我不确定如何实现此目标的最佳方法。 实际上有很多组件(pip,pip-tools,pipfile,pipenv…)以及可能的许多解决方案。

根据https://github.com/kennethreitz/pipenv/issues/966#issuecomment -339707418,它应该相对简单。 该dep解析逻辑主要来自pip工具。 我原本打算提交PR,但如果我们不愿意在花时间编写代码之前谈论我们希望API的外观,那么我就不能证明花费工作。

我目前正在考虑采用另一种方法-由于Pipfile是一种标准,因此与它的交互不需要通过pipenv进行,而且我想解决这里的其他一些奇怪的语义,例如按https删除现有的virtualenvs。

抱歉,我对一个已解决的问题发表评论,但是我想指出,据我所知,在我的项目中使用pipenv当前需要这样的工作流程:

pipenv install foo
vim Pipfile.lock  # Manually remove all the unwanted updates
git add && git commit && git push

我觉得很讨厌与团队成员进行交流。 替代方法似乎是将所有内容固定在Pipfile确切版本中,但这首先使使用pipenv的许多目的都无法实现。

IIUC,此行为等效于apt apt dist-upgrade每当运行apt install foo时执行隐式apt dist-upgrade apt install foo

pipenv install更新Pipfile.lock ,但没有将更新安装到本地virtualenv中,这使情况变得更糟。 如果开发人员没有仔细检查Pipfile.lock的差异,他们仍然在本地使用旧版本,但是一旦他们共享代码,所有其他环境都会看到令人惊讶的更新。 人们倾向于忽略Pipfile.lock的差异,因为它被认为是自动生成的文件。

我坚信“将所有内容更新到Pipfile允许的最新版本”应该是与“ install foo”分开的显式请求的操作。

应该固定在主人

该行为仍然存在,我在pipenv 11.8.3 ,@kennethreitz中对其进行了测试。

@ marius92mc “固定在主机中”注释是指最近发行版中添加的--selective-upgrade--keep-outdated选项: https: //docs.pipenv.org/#cmdoption -pipenv-install-keep过时的

这样一来,需要或想要精确控制何时升级的人们就可以选择加入该行为,而默认行为则继续尊重OWASP A9,并在每一个机会中推动急切的升级。

@ncoghlan我认为需要做的一件事(容易要求,而不是那么容易)是关于_how_这些选项的行为的常见问题解答(至少对我来说还是很困惑)。

例如:如果使用--selective-upgrade--keep-outdated ,即使它们与要更新的“ selected”包没有直接关系,仍会导致Pipfile.lock过时的库被更新。 。

听起来可能存在实现错误。

他们打算将pipfile.lock保持原样,除了新的更改。

让我知道提供测试Pipfile + .lock是否有帮助。

我认为您已经提供了足够的信息供我们进行调查。 我现在尝试这样做。

实际上,如果您的pipfile / lock包含了过时的结果,那就太好了。

@ncoghlan ,感谢您提供详细信息。
我再试一次您提到的选项,结果似乎是相同的,它仍然也会更新其他软件包,并在Pipfile.lock文件中进行更改。

@kennethreitz是否有任何有关此问题的更新?

抱歉,您的答案很慢。 我们还没有在这里确定回归的根本原因(我知道我本周末一直在处理数据中心迁移,所以我一直很慢),但是在接下来的几天中我们将对此进行分类。

一如既往的欢迎捐款!

我认为有一个缺少的用例可以使用相同的更改:开发应用程序时,我经常需要升级单个依赖项的版本。 我要遵循的步骤是:

  1. 更新setup.py中依赖项的版本限制
  2. 运行pipenv lock --selective-upgrade ; pipenv syncpipenv install --selective-upgrade "-e ."

@wichert如果Pipfile编辑方式使最低所需版本超出了当前锁定文件的最低要求,则--keep-outdated应该已经满足您的需求。 --selective-upgrade对于其中的情况下Pipfile并没有改变,但你要更新到新版本的固定反正。

@ncoghlan Pipfile尚未在这种情况改变了,只有setup.py通过改变最低版本要求的相关性,通常的东西更近,目前在Pipfile.lock

@wichert pipenv不会自动捕获对setup.py更改,因为它不是setuptools。 如果您希望这种情况发生,则必须运行pipenv lock

它的当前状态是什么? 3月25日,有人说他们认为实施问题将在“未来几天内”得到解决,并且由于已在此处跟踪其他错误报告,因此已经关闭。 但截至2018.7.1,我仍然看到Simon Percivall报告的错误(间接依赖项始终会更新),并且自原始报告以来尚未讨论该错误。 是否仍在跟踪问题?

(我目前居住在塞内加尔的二线城市,因此我的互联网非常糟糕,如果可能的话,不要在更新间接依赖项方面浪费我的数据,这将是一个游戏规则改变者:P)

PS:感谢您制作Pipenv,它很棒[3

是肯定的。 我们现在正在重写解析器以支持此操作。 它是在此版本中发行还是在下一版本中仍有待观察

我对我的编码技能没有足够的信心来估计解析器何时到达:p认真地说,这是一个完全自愿的项目,而且我们没有像商业环境中那样有截止日期的机制(我们甚至没有老板或项目经理或您公司中决定什么时候需要做的任何事情)。 如果您想在自己想要的时间范围内完成某件事,则需要自己完成,或者至少为其他人提供真正的动力。

@uranusjr FWIW,在@benkuhn的上述评论中,我没有看到对权宜之计的任何要求-只是有关事情在哪里的问题; 即完成了哪些工作,以便外部观察者可以做出自己的估计/决定。

我知道Pipenv是一个志愿者项目,并且非捐助者不能在没有签名的情况下要求在日期之前完成某件事。 我确实想知道,在项目的开发过程中是否还有提高透明度的余地,或者我是否只在正确的地方寻找。 通常的答案是“如果尚未更新问题,就没有动静”或“看看此WIP拉取请求”,但是尤其是这个问题似乎引发了更大的努力,因此很难找到圆点为那些不直接参与的人建立联系。

与往常一样,非常感谢您和每个人都付出宝贵的时间来改善Pipenv。 👏

可以肯定的是,这没有活动或正在进行的PR,因为它要复杂得多。 在内部,我们主要是在谈论我们如何相对于较大的项目构建此结构,并反复进行工作以建立一种可能甚至开始正常工作的方法。 一旦我们解决了这个问题,就可以建立解析逻辑。

同时,pipenv中的解析器堆栈非常复杂,我不愿意要求人们投入太多的精力来为此目的进行解缠。 即使是这里最简单的用例,也将需要大量的重构。 如果有人有兴趣帮助解决这个问题,我们很乐意审查/讨论任何建议的重构,但是两者紧密结合。

如果有人在依赖关系解析方面有专长,并且能够解决问题,我们当然会对输入感兴趣,但是目前还没有一个具体的想法。 我们经历了几次迭代,我们从未打算将其作为概念证明来发扬光大。 并非所有代码都成为PR,并且并非所有代码组织决策都在问题跟踪器上发生。 有时我们会同步聊天,并实时提出和删除想法。

我正在_____建议一些替代的工作流程,以解决此问题,这使安装时轻松固定到_Pipfile_中的特定版本成为可能。

我认为pipenv将foo = "*"解释pipenv install --pin foo这样的结果会导致foo = "==1.2.3"而不是foo = "*" (其中1.2.3是foo的当前最新版本)看起来像是救命。

但是,问题在于,许多软件包的行为可能会根据其依赖关系而发生很大变化(例如,同一版本的pylint可以根据所使用的astroid版本执行完全不同的操作),而软件包却没有准确地固定自己的部门。 因此,我认为这实际上不会使任何人走得太远。 :/

(才意识到我一直在评论错误的问题。很抱歉把事情搞砸了,请忽略我)

我已经苦苦挣扎了几个小时的实际用例:我想衡量Django 2.0项目中的测试覆盖率。 甚至pipenv install --keep-outdated --selective-upgrade --dev coverage坚持将非dev Django软件包更新为2.1版,由于其他地方的损坏,我绝对不能使用。 确实必须有一种方法来更改已安装软件包的集合,而不 最新版本中存在损坏的可能性将始终存在。

我将尝试@rfleschenberg的解决方法,但我不知道拥有一个可能不正确的_meta hash属性是否会破坏任何东西。

@ l0b0如果您的应用程序确实无法处理特定版本的Django,我认为在您的Pipfile中声明该限制是有意义的吗?

@AlecBenzer对我来说,这听起来像是setup.py的东西。

@wichert这也可能是有道理的(实际上我不太清楚在什么情况下要同时使用setup.py和Pipfile),但是如果您的Pipfile中有一行内容,则表示:

Django = "*"

您告诉Pipenv您希望它安装_any_版本的Django。 如果您真正想要的是安装2.0或更低版本,请告诉它:

Django = "<=2.0.0"

虽然在这种特殊情况下,pipenv并非出于真正原因升级Django,但可能是您尝试在某个地方安装需要Django> 2.0.0的软件包,此时,如果您没有告诉,pipenv会很高兴地安装它。您需要<= 2.0.0。

如果您真正想要的是安装2.0或更低版本,请告诉它

@AlecBenzer经过反思,现在我想到这是npm / yarn在安装软件包时默认执行的操作; 他们会找到最新的major.minor版本,并在package.json中指定^major.minor.0 ,即使明确要求升级到最新版本,也可以防止意外的主要版本升级。 我不知道Pipenv是否应该做同样的事情-但这将是一个单独的问题。

当然,它们的锁定文件也可以防止意外升级,即使是次要版本和修补程序版本也是如此。

我认为已经在上面和其他地方进行了讨论,但是在npm / yarn和pipenv之间的设计空间中存在着紧张/折衷。 表面上,任何程序包管理器都具有以下目标,并且具有相对优先级:

  • 易于安装和升级软件包
  • 难以通过错误的依赖关系升级意外破坏您的应用程序

在Pipfile中固定确切版本的麻烦在于,升级软件包变得更加困难。 这就是为什么存在pip-tools的原因(尽管它是用于requirements.txt的)。

正如重新打开问题时所说的那样, --keep-outdated标志似乎未按预期工作。 该行为是否应该是默认行为以及如何与其他程序包管理器保持一致并不是这里真正的中心问题。 让我们先解决这个问题。

@brettdh

经过思考,现在我想到这是安装软件包时npm / yarn默认执行的操作; 他们找到最新的major.minor版本,并在package.json中指定^ major.minor.0,即使明确要求升级到最新版本,这也可以防止意外的主要版本升级。 我不知道Pipenv是否应该做同样的事情-但这将是一个单独的问题。

是的,这与我尝试在https://github.com/pypa/pipenv/issues/966#issuecomment -408420493中建议的内容一致

听到此消息正在研究中,我感到非常兴奋!

同时,有没有人建议的解决方法比运行pipenv lock费力和容易出错,而不是运行

@benkuhn这不是我知道的-我一直都执行相同的锁定和还原舞蹈。

好的,您至少有时可以避免手动还原:

  1. pipenv lock
  2. git commit -m "FIXME: revert"
  3. pipenv install packagename
  4. git commit -m 'Add dependency on packagename'
  5. git rebase -i
  6. 删除FIXME: revert提交

不幸的是,如果您的Pipfile.lock开始包含的软件包版本太旧而无法满足packagename的要求,仍然有可能创建不一致的Pipfile.lock packagename ,但是pipenv可能会抱怨如果发生这种情况呢?

--keep-outdated似乎仅在Pipfile中指定(取消固定)的显式依赖项有系统地过时,而所有隐式依赖项均已更新。

我是否正确,使用pipenv==2018.7.1无法更新/安装单个依赖项而不更新其他依赖项? 我尝试了--selective-upgrade--keep-outdated不同组合,但均未成功。

手动编辑Pipfile.lock不好玩...

与@ max-arnold相同,这是我在现有项目中使用该工具的第一天,我不得不说,我真的很失望,在开始使用它之前,我检查了文档站点和视频演示,它看起来很不错对我来说,现在是这样:在实际项目中,使用pippipenv几乎是一样的,我不明白要点,就像线程中的许多其他人说的那样,锁定文件,如果不需要更新其他依赖项,为什么还要更新它们。

当然,###如果必须进行更新,则可以更新所有必需的依赖项,但是仅更新那些,而不是所有过时的依赖项。

此外,选项--selective-upgrade--keep-outdated不清楚有用的地方,这里还有另一个问题突出显示此问题#1554,没有人能够响应这些选项的作用,真是不可思议。

但是我主要的失望是为什么Python官方文档本身pip ,这也不能解决这些问题,但至少它是极简主义的,并且大部分都包含在任何环境中(不添加额外的依赖项)。

@mrsarm谢谢您的意见。 对不起,事情对您不起作用。 但是我不知道失望来自何处。 没有人将Pipenv强加于任何人。 如果它对您不起作用,请不要使用它。 这就是建议的工作方式。

您的咆哮者也没有与此问题特别相关的事物。 我了解这需要一些自我控制,以在事情不顺心时不向人丢垃圾,但是请表现出尊重,并避免这样做。

@uranusjr不是垃圾,这是一种意见,有时甚至不是一种选择,就像我的情况一样,有人选择pipenv创建一个我现在开始工作的项目,我必须处理这个问题。

但是现在情况变得最糟,我要说的不是意见,而是事实。

在尝试添加一个我为了避免处理此问题而避免使用的依赖项之后(因为它是开发人员依赖项,因此我使用pip和旧的requirements-dev.txt方法创建了第二个环境,该工具),我需要添加另一个依赖项。

新的依赖项是PyYAML,可以说是最新版本。 如果使用pip在任何新环境中安装它,您将看到该库未添加任何依赖项,因此仅安装PyYAML,在这种情况下使用Pip就是这么简单。 但是,使用Pipenv添加依赖项(因为我没有创建的项目是通过Pipenv进行管理的),尽管PyYAML没有任何依赖项,并且该项目先前未安装在该项目中(较旧的版本),也会发生相同的问题, pipenv更新了我在锁定文件和虚拟环境中的所有依赖关系,但是我不想更新其他依赖关系,我只是添加了一个没有任何依赖关系的新模块。

因此,结论(再次是一种观点,不是像pipenv这样的事实打破了我所有的依赖关系),是因为Pipenv代替了帮助我处理依赖关系管理,这使它陷入了困境。

我已经跟踪了几个月,而且我认为任何真正的项目最终都会在这个问题上绊倒,因为这种行为是意料之外的,违反直觉的,并且是危险的。

大约一个月前,我尝试了一种比pipenvpoetry更全面的选择; 它解决了_I_需要解决的问题:
1)管理一组依赖项(setup.py,setup.cfg,pip和pipfile-> pyproject.toml)
2)面向未来,向后兼容(再次pyproject.toml
3)完全没有意见(不,我真的不是要安装redis
4)以及经典Pipenv问题的解决方案:“此外,您还必须明确地告诉它[pipenv]在安装新软件包时不更新锁定的软件包。这应该是默认设置。” [[1](https://github.com/sdispater/poetry#what-about-pipenv)] [[2](https://github.com/pypa/pipenv/issues/966#issuecomment-339117289)]

我权衡了在pipenv问题上分享这些想法的可能性,但是正如

  • 作为免责声明,我不是诗歌团队的成员或与之隶属的团体。

ps:我认为,对Pipenv成为“官方”解决方案的担忧是由于它具有一流的集成性@ uranusjr可能会将其视为简单的建议,整个行业都将其视为“有福的做法”前锋”。 坦白的说,该建议在社区中比已经存在超过一年的某些PEP更权威。

没有人强迫您参加我们的问题追踪器; 如果您没有有效的评论,请找到一个不用于分类问题的论坛。

对于有兴趣尝试替代解析器@uranusjr的用户,而我本人已经实施了几个星期,请尝试https://github.com/sarugaku/passa ,它将生成兼容的锁定文件。 诗歌做了很多不同的事情,但是它本身也有局限性和问题,而且我们在设计哲学上对范围有分歧。

这是我们在业余时间管理的项目; 如果您希望解决某些问题或有更好的方法,我们很乐意接受您的贡献。 如果您只是在这里告诉我们,我们毁了您的一天和您的项目,我只想请您一次看看。

我们没有忘记或忽略此问题,我们已在上面链接的解析器中完全实现了修复程序。 有耐心,有礼貌或在其他地方聊天。 对于一直耐心等待修复的用户,请尝试使用上述解析器-我们很想知道它是否满足您的需求。 它实现了适当的回溯和解决方案,不应处理此升级策略

在短期内,我认为如果我们不首先结束学习,我们可以为此获得创可贴。

@dfee我不太确定应用程序和库之间的界线模糊是否是依赖关系管理的正确答案,因此我不认为诗歌的方法具有优势。 无论您的问题与推荐引擎有什么关系,我都没有参与,但是我们早些时候就解决了……

@techalchemy

我不太确定应用程序和库之间的界线模糊是否是依赖管理的正确答案,因此我不认为诗歌的方法有什么优势。

为什么呢我从未理解过应该以不同的方式管理库和应用程序的依赖关系的想法。 两者之间的唯一区别是应用程序需要使用锁定文件来确保可重现的环境。 除此之外,这是一回事。 这是大多数其他语言中的标准,由于某些原因,Python在这里似乎是个例外,并且从用户体验的角度来看,这是不好的,因为这使事情变得比原本应该的复杂。

它也有局限性和问题本身

哪个? 我真的很好奇您在使用诗歌时遇到的问题或局限性。

我对豆的歉意如此无礼。 现在阅读我的评论后,我意识到尽管我提供了信息并且我的某些选项仍然有效(IMHO),但我写我想说的话的方式并不合适。

我知道问题跟踪器最适合讨论错误和改进,并讨论是设计错误还是错误,在线程中尚不清楚,但我深表歉意。

我想这里有两个重要的话题:

  • Pipenv应该在尝试安装新依赖项的地方更新所有过时的依赖项:不需要更新的依赖项,因为我们要安装的新软件包/版本可以与现有的依赖项一起使用,甚至可以我们要安装的新软件包的依赖性吗? 也许这超出了本票的范围,但这是一个非常重要的话题。
  • 这些参数--keep-outdated --selective-upgrade可以使我们避免这些行为? 目前尚不清楚这些选项的作用,缺少有关它们的文档,甚至在相关问题(#1554)中也没有人回答。

万一这是这些参数中的一个错误--keep-outdated --selective-upgrade ,我仍然认为不要设置任何参数来解决依赖项的不必要更新,这是一个非常糟糕的主意。

与类似的情况进行比较,假设您执行apt-get install vim只是在系统中安装了vim工具(以及必要的vim依赖项或更新,如果适用),但是还可以想象在这种情况下apt更新系统的所有其他依赖项:python,QT系统,Linux内核等。 不是说apt不允许我们更新其他依赖项,而是有一个明确的命令可以做到这一点: apt-get upgrade ,而apt-get install PACKAGE只是安装/更新PACKAGE及其依赖项。

@sdispater区别是我们所遇到的每一个分歧的核心,它令人难以置信的微妙,但我想指出您的是https://caremad.io/posts/2013/07/setup-vs-requirement/有关长生不老药使用案例的文章: http :

pyproject.toml确实不支持库定义元数据-根本不支持未实现peps 517和518的任何版本的pip(这两个都仍在制定实现细节中)是权威的库声明文件。 为此目的存在setup.cfgsetup.py的实际继承者)和恕我直言,这两个都应该得到支持。 发布了一个库,该库旨在供具有抽象依赖关系的用户使用,以便它们可以在沙箱中与他人很好地玩耍。 应用程序通常是大型的,复杂的野兽,有时具有数百个直接依赖项。 因此,我们的主要差异之一是在设计和构建工具时,我们还要考虑到这一点

@mrsarm对于第一个问题,更新行为是有意的(当时/ cc @ncoghlan进行了广泛讨论,并涉及OWASP安全问题)。 在第二点上,该行为当前未正确实现,这就是问题仍然存在的原因,这导致我们重写了pipenv背后的后备解析器,如上所述。 它根本不支持这种行为。 --selective-upgrade应该只选择性地升级属于新软件包的依赖项,而--keep-outdated会保留满足新软件包要求的依赖项的所有内容。 稍有不同,但我可以肯定,两者现在都无法正常工作。

pyproject.toml实际上不受库定义元数据的支持-根本没有将peps 517和518(都仍在制定实现细节中)实现为权威库声明文件的任何版本的pip都不支持。 为此存在setup.cfg(setup.py的实际后继者)和恕我直言,这两个都应该得到支持。

好吧,这当然不是话题,但这是一个重要的讨论,所以我不能自救。

实际上,除了distutils和setuptools建立的约定外,目前在setup.cfg周围没有任何标准。 pyproject.toml绝对是库元数据,因为是setup.py的后继者,否则社区会在setup.cfg放置构建要求。

pyproject.toml描述了如何构建项目(PEP 518),并且构建的一部分正在描述元数据。 我并不是说pyproject.toml需要此元数据的标准位置,但是PEP 518使用此文件来安装构建工具,并且可以合理地期望该构建工具将从其他地方使用声明性配置。在文件中确定如何构建项目。

无论如何,回到pipenv vs诗歌-似乎有一些想法浮出水面,即应用程序不需要库获得的某些功能(例如入口点),这是不正确的。 一个应用程序成为python包应该很简单。

在我对python和其他生态系统的经验中,应用程序和库之间的唯一真正区别是您是否使用锁文件。 当然,在第三种情况下,您实际上只想要requirements.txtPipfile而没有实际代码,这似乎是pipenv迄今为止关注的全部内容( pipenv install -e .下跌之所以归为此类,是因为pipenv仍然不敢尝试支持程序包元数据。 不幸的是,尽管使用这种方法可以使Pipenv的设计更简洁,但它对大多数应用程序的用处也较小,因为PEP 518决定将项目安装到可编辑模式,因此为了继续使用pipenv,我们将被困在setuptools上更长的时间,因为您不能使用pyproject.toml来退出setuptools并仍然使用pipenv install -e .

除了distutils和setuptools建立的约定外,setup.cfg周围目前实际上没有任何标准。 pyproject.toml绝对是用于库元数据的,因为setup.py的后继者,否则社区会在setup.cfg中放置构建要求。

Distutils是标准库的一部分,setuptools现在随pip一起安装,因此说没有标准有点愚蠢。 更不用说它使用pep 345中概述的元数据等标准,并且还可以用于指定构建要求。

社区将把构建要求放到setup.cfg中。

你是说鼓舞士气的作者吗? 您可以问他们为什么做出他们的决定,他们会在开始时概述所有这些。

pyproject.toml描述了如何构建项目(PEP 518),构建的一部分正在描述元数据。 我并不是说pyproject.toml需要此元数据的标准位置,但是PEP 518使用此文件来安装构建工具,并且可以合理地期望该构建工具将使用文件中其他位置的声明性配置。确定如何构建项目。

这是最近出现在邮件列表上的-除了用于声明构建系统要求的任何地方,没有其他地方在pyproject.toml附近声明标准。 其他一切都是假设; 您可以将其称为“库定义元数据”,但事实并非如此。 尝试仅定义一个没有有关您的项目的其他信息的构建系统(即没有符合pep-345的元数据),然后将其上传到pypi,让我知道如何进行。

无论如何,回到pipenv vs诗歌-似乎有一些想法浮出水面,即应用程序不需要库获得的某些功能(例如入口点),这是不正确的。 一个应用程序成为python包应该很简单。

谁在说应用程序不需要入口点? Pipenv具有处理此问题的完整结构。

因此,为了继续使用pipenv,我们将在setuptools上停留更长的时间,因为您无法使用pyproject.toml来退出setuptools并仍然使用pipenv install -e。

不遵循这里...我们不会永远让pip版本10永远消失,我从字面上一直在描述我们的新解析器,而实际的安装程序只是直接回到pip ...这如何防止人们使用可编辑内容安装?

这是最近出现在邮件列表上的-在pyproject.toml附近没有任何地方声明标准

没错,这不是“标准”,但是在同一线程中,他们通过将其称为pyproject.toml可能会要求人们将该文件用于其他与项目相关的设置/配置。

因此,按照您在此处调用的相同逻辑:

Distutils是标准库的一部分,setuptools现在随pip一起安装,因此说没有标准有点愚蠢。

pyproject.toml是一个标准,社区已将其用作放置与构建系统以及Python项目其他部分有关的信息的标准位置。

不遵循这里...我们不会永远让pip版本10永远消失,我从字面上一直在描述我们的新解析器,而实际的安装程序只是直接回到pip ...这如何防止人们使用可编辑内容安装?

PEP 517在可编辑安装中受到了干扰……这意味着,如果您不使用安装工具(以开发模式将项目安装为可编辑模式的安装工具),则没有标准方法可以以可编辑模式安装项目。

Distutils是标准库的一部分,setuptools现在随pip一起安装,因此说没有标准有点愚蠢。 更不用说它使用pep 345中概述的元数据等标准,并且还可以用于指定构建要求。

是的,构建系统应该输出PEP 345中描述的PKG-INFO文件。这是一种传输格式,以sdist或wheel形式出现,是从setup.py/setup.cfg生成的,不能替代例如面向用户的元数据。 PEP 518的pyproject.toml用途是支持distutils / setuptools的替代版本作为构建系统,现在没有人试图替换sdist / wheel格式。 这些替换的构建系统需要放置元数据的位置,幸运的是,PEP 517为这些系统保留了tool.命名空间。 这不是一个假设-flit和poetry都为“库定义元数据”采用了此命名空间。

尝试仅定义一个没有有关您的项目的其他信息的构建系统(即没有符合pep-345的元数据),然后将其上传到pypi,让我知道如何进行。

有建设性。

谁在说应用程序不需要入口点? Pipenv具有处理此问题的完整结构。

这个结构在哪里? 我什至在https://pipenv.readthedocs.io/en/latest/的pipenv文档的任何页面上都找不到“ entry”一词,所以“整个结构”听起来很牵强吗? 如果您是指可编辑的安装,那么我们已经达到了我在上面所说的观点-Pipenv决定将自身与pipenv install -e .耦合,作为可以预见并在将来以套件形式开发应用程序的唯一方式,以支持可预见的未来Pipenv这里与setuptools耦合。 我认为整个争论真的可以归结为这一点,人们(当然是我)很沮丧,因为我们现在可以定义不使用setuptools但不能使用pipenv开发它们的库。 完全清楚地说,这并不是严格意义上的pipenv的过错(PEP 518决定在可编辑的安装中撑腰),但拒绝承认该问题在讨论中令人沮丧,因为诗歌提供了一种以符合标准的方式处理此问题的替代方法格式为pyproject.toml 。 Pipenv一直说诗歌会做出错误的决定,但实际上并没有尝试提供前进的道路。

@bertjwregeer

pyproject.toml是一个标准,社区已将其用作放置与构建系统以及Python项目其他部分有关的信息的标准位置。

太好了,我们很乐意容纳使用此系统构建的sdist和wheel,直到有可编辑安装的标准,我们将继续追求使用pip来构建sdist和wheel和以这种方式处理依赖项解析。 请完整阅读我的回复。 pip,相关peps的作者和维护者以及我和@uranusjr非常了解可编辑安装之间的差异以及在pep 517和518的限制下构建它们的含义。到目前为止,我所看到的一切是不是有问题的peps并未专门解决如何构建它们的问题,因为它们由工具负责,出于某种原因,每个人都认为这意味着pipenv只能使用setuptools吗?

我已经说过这是不正确的。 如果您实际上对实现感兴趣,并且进行了富有成效的对话,那么我很乐意。 如果您只是在这里说我们不知道我们在做什么,但是对首先了解我们在做什么并不感兴趣,这是您的唯一警告。 我们是时间有限的志愿者,我正在对有毒物质奉行零容忍政策。 我不假装自己的工作是完美的,也不假装pipenv是完美的。 我将很乐意为这种讨论贡献自己的时间和精力; 作为交换,我要求他们保持尊重,坚持事实,参加活动的人也愿意学习,倾听和倾听我的声音。 如果您只是在肥皂盒里,您将不得不寻找另一个平台。 这是一个问题跟踪器。 我将在必要时进行审核。

这次讨论是不合时宜的。 如果有人对当前问题有建设性的意见,请随时继续讨论。 如果有人对我们的构建系统实现有疑问或疑问,请打开一个新的期刊。 如果您对我们的文档有疑问,我们会接受许多关于文档的拉取请求,并且我们知道它需要工作。 请将所有讨论推迟到这些主题的新问题上。 请注意:相同的规则仍将适用-这不是肥皂盒,而是问题跟踪器。

https://pipenv.readthedocs.io/zh-CN/latest/advanced/#custom -script-shortcuts
请阅读文档。

入口点是一个比控制台脚本更通用的概念,并且此链接在解决这些问题时是完全错误的。 <soapbox>禁止访问-您不是这里的大型开源项目的唯一维护者,而且我的评论都没有对您或项目造成人身攻击。 之所以在此发表评论,是因为他们想要使用pipenv并欣赏它的许多功能,因此愿意这样做。 我的评论不是该主题的第一篇非主题文章,但仅是被标记的内容。 您昧的评论表明您认为我不知道我在说什么,这是令人尴尬且有毒的。

在我们维护的项目中,我们可以肥皂盒化。 是的,pip将支持你们两个人似乎都完全理解的所有兼容的构建系统,这些系统会生成消耗性元数据,并且正如我所描述的,由于pipenv使用pip作为支持工具来驱动其安装过程,是的,pipenv将支持所有兼容的构建系统。工具。 我已经说过了

是的,请把你的毒性带到其他地方。 在这里不欢迎您的态度。 最后警告。 持久的煽动冲突的企图是不能容忍的。

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