Pip: pip 9.0.2 中的“import pip”出错

创建于 2018-03-17  ·  71评论  ·  资料来源: pypa/pip

一些用户现在在使用 pip 9.0.2 的函数中调用import pip时遇到导入错误。 降级到 9.0.1 解决了这个问题。

追踪: https ://user-images.githubusercontent.com/2273226/37558391-5e41fc94-2a24-11e8-9fdc-5884445e829a.png

更多细节在这里:
https://github.com/Miserlou/Zappa/issues/1446

backwards incompatible auto-locked maintenance

最有用的评论

来吧.. 在单个x.x.PATCH版本的碰撞中做出巨大的突破性改变? 对于称为“主要”的顶级方法? 我认为这是相当糟糕的形式..

所有71条评论

我也可以确认这一点。 刚要提出同样的问题。

这是 #5079 的欺骗——导入 pip 不是受支持的用例(而且从来没有)。

来吧.. 在单个x.x.PATCH版本的碰撞中做出巨大的突破性改变? 对于称为“主要”的顶级方法? 我认为这是相当糟糕的形式..

这也破坏了 Anaconda,我想出了与@Miserlou相同的解决方案:

https://github.com/ContinuumIO/anaconda-issues/issues/8911

许多项目都报告了错误。

当我尝试使用 pip 更新我的 anaconda-navigator 时,这个错误也困扰着我。

我们是否有机会获得修复此问题的 9.0.3 - 理想情况下很快?

这已经影响到许多主要项目(Anaconda、SpaCy、Zappa),仅在 GitHub 上就有超过 85 万次使用,现在被这个所谓的“补丁”版本更新破坏了。

您能否至少恢复 9.0.3 中的这一巨大变化,然后向下游_宣布_您打算在未来的 10.xx 或至少 9.xx 版本中更改此行为的意图?

我们也不想使用旧版本,但这正是我们最终要做的。 我们的 CI 环境中不存在 9.0.2,至少目前是这样。

在一些 OpenStack 项目中也看到了这一点。

Pip 10 将在大约一个月后发布。 据我了解,问题在于使用import pip访问 pip 的内部功能的代码。 我们从未正式支持这种用法,并且我们已经明确记录了一段时间以来缺乏支持(尽管仅在 https://pip.pypa.io/en/latest/user_guide 的文档的“最新”版本中) /#using-pip-from-your-program,因为自从添加了该文档部分以来,我们还没有新的稳定版本)。 去年 10 月,我们还宣布对内部进行重组,以明确不支持使用内部 API(请参阅 https://mail.python.org/pipermail/distutils-sig/2017-October/031642.html)。 无论 pip 9.0.3 版本可能做什么,pip 10 中的更改都将破坏任何此类用法。 因此,很难将其视为突然的、意外的破坏。

如果@dstufft想要发布紧急 9.0.3 版本,我可以接受。 但这只是一个非常短期的好处,我有点失望人们还没有离开import pip 。 受此问题影响的人仍然需要为 pip 10 做准备,并且应该明白,简单地切换到import pip._internal并不是我们支持或推荐的方式。

重新引入某种程度的 API 支持的建议当然是一种选择(例如,参见 #5080),但在现阶段,任何此类更改都为时已晚,无法将其纳入 pip 10。

对于那些使用旧方法的人来说,代码没有发出警告,没有任何以 _ 开头的“内部”表示,这只是一个错误修复凹凸,我实际上认为很容易将其视为突然的、意外的破坏.

是的,这是人们可以从MAJOR版本更新中获得的变化类型。 那会很好。

不幸的是,这个巨大的变化是在PATCH更新中出现的,它_应该是修复问题,而不是破坏它们_。 这与语义版本控制完全相反。 结果,我们看到整个 Python 生态系统受到了巨大的破坏。

您应该尽快在另一个PATCH更新中恢复此更改,然后在MAJOR版本更新中进行重大的重大更改。 既然你已经过早地为每个人打破了一切,我想他们会更加意识到真正的重大变化即将到来。

我还认为,考虑到它_没有_在稳定文档中记录,并且公告说中断将发生_对于主要版本_,而不是一个月的补丁事先的。

拜托,只是让每个人都头疼,恢复这个问题并开始真正遵守语义版本控制。

@Miserlou好的,我明白你的意思——我们针对 pip 10 的内部重命名更改,因为它是一个主要版本。 我真的不知道补丁发布的驱动程序 - @dstufft 向我发送了有关它的信息,显然是为了避免 Mac OS 用户在即将到来的 TLS 支持截止日期(即 pip 10 发布之前)出现重大损坏。 我们预计这些问题会严重到足以保证短期补丁发布。 当然没有破坏现有用法的意图。

我必须将后续 9.0.3 的决定留给@dstufft - 我不知道 9.0.2 的详细信息,也不知道是否有可能确定如何解决这个问题。 而且我无法判断完全取消 9.0.2 是否会带来整体收益,因为我不知道有多少人受到 Mac OS 问题的影响。 我知道(至少对某些人而言)固定到 9.0.1 是一种解决方案,因此这可能最终成为最不坏的选择。

macOS TLS 问题将影响在 macOS<10.13 上使用系统 Python 的所有人

我必须将后续 9.0.3 的决定留给@dstufft

我和@pfmoore 的立场相同。

解决方法(如果您有可用的)是检查导入顺序并测试将导入 pip 移到其他包导入之上(具体来说,导入 pip _before_ importing requests 似乎可以解决某些情况)。 (请注意,这仍然意味着使用 pip 的内部结构,这不是官方支持的。)

与 docker python 3.4 的 gitlab-ci 中的 pip 9.0.2 相同的问题:KeyError

  File "/usr/local/lib/python3.4/site-packages/pip/__init__.py", line 45, in <module>
    from pip.vcs import git, mercurial, subversion, bazaar  # noqa
  File "/usr/local/lib/python3.4/site-packages/pip/vcs/mercurial.py", line 9, in <module>
    from pip.download import path_to_url
  File "/usr/local/lib/python3.4/site-packages/pip/download.py", line 40, in <module>
    from pip._vendor import requests, six
  File "/usr/local/lib/python3.4/site-packages/pip/_vendor/requests/__init__.py", line 98, in <module>
    from . import packages
  File "/usr/local/lib/python3.4/site-packages/pip/_vendor/requests/packages.py", line 12, in <module>
    sys.modules['pip._vendor.requests.packages.' + mod] = sys.modules["pip._vendor." + mod]
KeyError: 'pip._vendor.urllib3.contrib'

仅供参考,9.0.2 发布时带有损坏的构建:
screenshot_2018-03-20_08-43-35

Travis-CI 参考: https ://travis-ci.org/pypa/pip/builds/354616774?utm_source=github_status&utm_medium=notification

当然,这些错误可能无关紧要,尽管这听起来像是“匆忙发布”......

@pfmoore

如果@dstufft想要发布紧急 9.0.3 版本,我可以接受。 但这只会是一个非常短期的好处,我有点失望人们还没有放弃进口点子。 受此问题影响的人仍然需要为 pip 10 做准备,并且应该理解简单地切换到 import pip._internal 不是我们支持或推荐的。

我不敢相信这是该存储库所有者的声明......您实际上只是说“f*ck 语义版本控制”和“无论如何谁需要弃用政策”。

pip 总是被记录为没有可消耗的 python api,我对那些即使在那时试图扭转“多年来告诉你”业力的人感到失望

@RonnyPfannschmidt这就像说“我们已经告诉过你 100 次你不能超过限速”,然后通过用燧石车替换所有引擎车来执行限速,这样人们就不能越过限速了。

你刚刚完美地证明了转过头来这么糟糕 - 告诉是“不要依赖它它会崩溃” - 现在它坏了,突然之前告诉你它会坏的项目是错误的

那只是因为你不喜欢过错而责备

@RonnyPfannschmidt

那只是因为你不喜欢过错而责备

所以你说我使用依赖于 pip 未记录功能的3rd-party包是错误的。 也许,我……我应该筛选那些 3rd-party 包的错误并提交一个问题,甚至更好的 PR。

但让我们面对现实:有很多用于生产的项目现在都被破坏了。 这不是道德问题,也不是这是谁的错的问题。 这是“您能否解决此问题并提供适当的警告/弃用”的问题。

如果您使用的第三方包由于依赖于未记录的、无保证的内部 API 而中断,那么在我看来,您应该针对该包提交错误。

pip的哪些部分是和不打算供第三方使用之间有一条易于发现的界限,我不支持试图强迫其开发人员维护本不应该维护的内部 API由第三方包使用。 我不支持将其视为pip开发人员的错,并以他们的方式发送愤怒的用户。 如果您想对某人生气,请对您使用的任何依赖于内部 API 的包生气,并推动他们的维护人员修复他们自己的代码。

@anx-ckreuzberger

我不敢相信这是该存储库所有者的声明......您实际上只是说“f*ck 语义版本控制”和“无论如何谁需要弃用政策”。

虽然我理解这里的挫败感,但我越来越恼火的是人们愿意将我们从未承诺过的事情归咎于 pip 维护者。

如果你想提出这样的指责,请支持他们

  1. 指向来自任何 pip 维护者的声明的指针,我们支持在用户代码中使用 pip 内部 API。
  2. 指向来自 pip 使用语义版本控制的任何 pip 维护者的语句的指针。

我不认为你会找到那个证据...

所以你说我使用依赖于 pip 未记录功能的 3rd-party 包是错误的。

不,但是指责 pip 维护者而不是那些项目是不可接受的。 我们正在努力帮助您,但不对这些项目所做的事情负责。 向他们表达你的不满。

但让我们面对现实:有很多用于生产的项目现在都被破坏了。 这不是道德问题,也不是这是谁的错的问题。 这是“您能否解决此问题并提供适当的警告/弃用”的问题。

我们试图提供警告。 我们几个月前发布了公告,我们添加了解释情况的文档,并且我们一直在回复跟踪器上的问题,指出不支持使用内部 API。 添加弃用远没有您建议的那么容易,因为 pip 本身会发出这些警告(或者 pip 有一种方法可以关闭它们,其他人只会复制 - 我们已经听说有人计划只是进口pip._internal ,所以即使是这种变化也不会阻止他们:失望:)。

至于“修复”这个问题,我很高兴地承认 9.0.2 的发布很快就解决了一个紧迫的问题,而我们没有预料到这个问题。 也许发布一个 2-3 周的 9.0.3 版本是一个合理的做法,我自己不这么认为,但我已经说过我们会考虑这一点。 我个人不能同意这样做,因为我不是参与 9.0.x 版本的人。 我正在研究 pip 10,这将使所有这些辩论变得无关紧要,所以这可能是我在这个问题上的最后一句话——我需要专注于与该版本相关的事情。

我的个人建议:

  1. 如果您受此影响并且现在需要解决方法,请固定到 9.0.1。
  2. 为 pip 10 做好准备,当您当前拥有的所有依赖项因使用 pip 内部 API 而被破坏时,它们将再次破坏。 推动这些依赖关系对我们几个月来一直提供的信息采取行动,并很高兴您提前得到警告,它会发生。
  3. 如果 pip 9.0.3 被释放,请移除 pi​​n。
  4. 在 pip 10 beta 发布时对其进行测试,并将任何问题报告给相关方(如果他们在内部调用 pip,则为第三方项目,如果您自己调用 pip,则为我们)。

我在 docker 容器中使用 pip 9.0.2 和 Python 2.7.14 遇到了同样的问题。
不过,我无法在 docker 容器外的开发机器上重现该问题。
我搜索了一个 pip 导入(grep'd for import.pipfrom.pip\'pip\"pip )但找不到任何东西。
我们在 Plone 正在使用一种机制来自动包含 setuptools setup.py 文件中包含的包的配置,这听起来很可疑 - 但同样 - 这个只是使用来自 pip AFAIcansee 的__import__和 nothign。

这是回溯的相关部分:

  File "/home/plone/.buildout/shared-eggs/zope.configuration-3.7.4-py2.7.egg/zope/configuration/xmlconfig.py", line 359, in endElementNS
    self.context.end()
  File "/home/plone/.buildout/shared-eggs/zope.configuration-3.7.4-py2.7.egg/zope/configuration/config.py", line 558, in end
    self.stack.pop().finish()
  File "/home/plone/.buildout/shared-eggs/zope.configuration-3.7.4-py2.7.egg/zope/configuration/config.py", line 706, in finish
    actions = self.handler(context, **args)
  File "/home/plone/.buildout/shared-eggs/z3c.autoinclude-0.3.7-py2.7.egg/z3c/autoinclude/zcml.py", line 51, in includeDependenciesDirective
    info = DependencyFinder(dist).includableInfo(['configure.zcml', 'meta.zcml'])
  File "/home/plone/.buildout/shared-eggs/z3c.autoinclude-0.3.7-py2.7.egg/z3c/autoinclude/dependency.py", line 26, in includableInfo
    module = resolve(dotted_name)
  File "/home/plone/.buildout/shared-eggs/zope.dottedname-4.2-py2.7.egg/zope/dottedname/resolve.py", line 39, in resolve
    found = __import__(used)
  File "/plone/buildout/lib/python2.7/site-packages/pip/__init__.py", line 45, in <module>
    from pip.vcs import git, mercurial, subversion, bazaar  # noqa
  File "/plone/buildout/lib/python2.7/site-packages/pip/vcs/mercurial.py", line 9, in <module>
    from pip.download import path_to_url
  File "/plone/buildout/lib/python2.7/site-packages/pip/download.py", line 40, in <module>
    from pip._vendor import requests, six
  File "/plone/buildout/lib/python2.7/site-packages/pip/_vendor/requests/__init__.py", line 98, in <module>
    from . import packages
  File "/plone/buildout/lib/python2.7/site-packages/pip/_vendor/requests/packages.py", line 12, in <module>
    sys.modules['pip._vendor.requests.packages.' + mod] = sys.modules["pip._vendor." + mod]
zope.configuration.xmlconfig.ZopeXMLConfigurationError: File "/plone/buildout/parts/instance/etc/site.zcml", line 15.2-15.55
    ZopeXMLConfigurationError: File "/plone/buildout/parts/instance/etc/package-includes/002-bda.aaf.site-configure.zcml", line 1.0-1.56
    ZopeXMLConfigurationError: File "/plone/buildout/src-aaf/bda.aaf.site/src/bda/aaf/site/configure.zcml", line 11.2-11.48
    ZopeXMLConfigurationError: File "/plone/buildout/src-aaf/bda.aaf.site/src/bda/aaf/site/configure-dependencies.zcml", line 10.2-10.39
    ZopeXMLConfigurationError: File "/plone/buildout/src-addons/plone.app.mosaic/src/plone/app/mosaic/configure.zcml", line 9.2-9.39
    ZopeXMLConfigurationError: File "/home/plone/.buildout/shared-eggs/plone.app.tiles-3.0.3-py2.7.egg/plone/app/tiles/configure.zcml", line 18.2-18.41
    ZopeXMLConfigurationError: File "/plone/buildout/src/plone.app.z3cform/plone/app/z3cform/configure.zcml", line 10.2-10.41
    ZopeXMLConfigurationError: File "/plone/buildout/src/plone.app.widgets/plone/app/widgets/configure.zcml", line 12.2-12.41
    ZopeXMLConfigurationError: File "/home/plone/.buildout/shared-eggs/Products.CMFPlone-5.1.0.1-py2.7.egg/Products/CMFPlone/configure.zcml", line 15.2-15.46
    ZopeXMLConfigurationError: File "/home/plone/.buildout/shared-eggs/plone.app.contenttypes-1.4.9-py2.7.egg/plone/app/contenttypes/configure.zcml", line 10.2-10.37
    KeyError: 'pip._vendor.urllib3.contrib'

据我了解,仅导入 pip - 不使用它 - 已经中断。 这不是 Python 领域的良好公民行为。 不支持使用它/不提供公共 API 是一回事,只是在导入时中断了另一件事。 这会影响很多自动检查代码。

可以这样想:pip 是一个命令行实用程序,而不是一个库。 它是用 Python 编写的这一事实是无关紧要的。 这就是事情的真相。

@pfmoore

虽然我理解这里的挫败感,但我越来越恼火的是人们愿意将我们从未承诺过的事情归咎于 pip 维护者。

可以这样想:pip 是一个命令行实用程序,而不是一个库。 它是用 Python 编写的这一事实是无关紧要的。 这就是事情的真相。

最重要的是,你承诺什么并不重要。 重要的是你做了什么以及结果是什么。 也许你认为它是一个命令行实用程序。 但是您将其作为库发布。 这就是事情的真相:

你发布了一个带有 Feature X 的库。人们开始使用 Feature X。当然,你说过“伙计们,请不要使用 Feature X”。 但是你一直用 Feature X 发布它。多年来。 所以人们一直在使用它。 成千上万的项目,无论大小,现在都在使用它。 突然,您在没有足够警告的情况下在小更新中将其删除。

你认为接下来会发生什么?

在短期内,除非有充分的理由,否则人们只会固定旧版本而不取消固定它。

从长远来看……嗯,取决于有多少人认为更换您比修复您损坏的所有东西更具成本效益。

@pfmoore你在我上面引用的回溯中看到可疑的东西吗? 没有使用任何 pip 内部 AFAIK。 有趣的是,大多数人在 docker 容器中都有这个问题。

@all,指责维护人员破坏代码无助于解决问题。

可以这样想:pip 是一个命令行实用程序,而不是一个库。 它是用 Python 编写的这一事实是无关紧要的。 这就是事情的真相。

事实:如果由于某种原因即使通过自动检查代码导入它也无法导入:全部中断。 我想这发生在@thet的情况下。
结论:pip 必须将自身与其安装包的全局或当前 virtualenv/venv Python 命名空间隔离开来。 这样它就不会污染它,甚至不会发生意外进口。

首先,对不起,如果我指责回购的维护者有错误的代码。 任何指控都是出于挫败感,如果有的话,请指出恕我直言, 9.0.2 版本是根据 semver 的定义发布的补丁版本(尽管@pfmoore明确表示 pip 不一定使用 semver - 这我猜是另一天的另一个问题)。

@迈克哈特85

在短期内,除非有充分的理由,否则人们只会固定旧版本而不取消固定它。
从长远来看……嗯,取决于有多少人认为更换您比修复您损坏的所有东西更具成本效益。

差不多。 我的意思是看一下 JavaScript 包管理器:npm、bower、yarn,无论是明年~一周发布什么

不,但是指责 pip 维护者而不是那些项目是不可接受的。 我们正在努力帮助您,但不对这些项目所做的事情负责。 向他们表达你的不满。

我知道我(我们的?)在这个问题上的不满可能会被误导。 尽管您必须承认,很难说服任何人这是 3rd-party-maintainers 的错。

我们试图提供警告。 我们几个月前发布了公告,我们添加了解释情况的文档

这是针对 pip 9.0.2 还是针对 pip 10? 如果是针对 pip 9.0.2,如果Changelog中有注释,我会觉得很好。 无论如何,感谢您非常积极地参与 pip 10 的开发并发布了关于不使用import pip的公告,这很好! 保持!

添加弃用远没有您建议的那么容易,因为 pip 本身会发出这些警告(或者 pip 有一种方法可以关闭它们,其他人只会复制 - 我们已经听说有人计划只是import pip._internal,所以即使是这样的改变也不会让他们失望)。

我认为这不会太难......你已经在__init__.py中拥有它:

if __name__ == '__main__':
    sys.exit(main())

添加一个else怎么样?

if __name__ == '__main__':
    sys.exit(main())
else:
    logger.warning("You are importing PIP as a Python library. This behaviour is deprecated and should no longer be used. We will break the API with version 10.0!!!111eleven Please see https://pip.readthedocs.org/some_link_where_you_explain_this.html")

编辑:如果你想对它“严格”,你甚至可以在这里提出一个异常,并在子模块中添加类似的语句。

人们会解决这个问题的事实是另一回事。 如果你想破解一个库,你可以随时对其进行逆向工程。 你总能找到解决方法。 但是你不应该在你的设计决策中考虑所有的方法。

从长远来看……嗯,取决于有多少人认为更换您比修复您损坏的所有东西更具成本效益。

我总是觉得这种“威胁”很有趣。 它伴随着一个根本性的误解,即对 pip 之类的工作量以及实际成本(以及实际上愿意为它支付的人有多少)付出了多少努力。 如果你觉得你能够做得更好,那么一定要这样做,我(我假设其他人)欢迎它。 在过去的几年中,大量的努力一直在记录和设计标准,其中一个明确的目标是使这样的事情发生成为可能。

保持对这些事情的看法很重要。 有..少于15个? 20? 人们评论这是如何破坏他们的(尽管这些指标总是存在“冰山一角”的问题),同时 pip 9.0.2 已经是过去一周使用量第二大的安装程序(算上它甚至不存在的天数) for) 并且自发布以来已经从 PyPI 下载了 1700 万个文件。 仅从最后一天来看,它已经超过 pip 9.0.1 成为 PyPI 上最常用的安装程序的 80%。

因此,虽然我认识到这对某些人来说是破坏性的,但相对少数人在做不受支持的事情,或者在相当边缘的情况下做事。

如果我能找到时间,我可能会尝试削减 9.0.3,主要是为了解决@thet遇到的情况,它只是一个尝试导入东西的自动导入器,而他们实际上并没有尝试使用pip 的内部 API 以任何方式。 如果这也最终解决了使用 pip 的内部 API 的人的行为,我不会特意打破它们,但如果不是,我也不会竭尽全力修复他们也特别。

请注意,此时发布 9.0.x 需要很多小时( master中的事情已经发生了足够的分歧,以至于需要一些技巧才能发布)并且这不计算调试所需的时间并解决实际问题。 如果您想增加发生这种情况的机会,那么进行调试和修复并提供补丁(或您自己的 fork 中的 9.0.2 标签的分支)是最好的方法。

首先,对不起,如果我指责回购的维护者有错误的代码。 任何指责都是出于沮丧

谢谢你。 这里的挫败感很高,我理解这一点。

添加一个else怎么样?

好主意——我希望我们前段时间就想到了这一点。 当然,现在没有实际意义,因为内部命名空间将在 pip 10 中重新组织,所以为时已晚。 我以后一定会记住这个技巧的。

这是针对 pip 9.0.2 还是针对 pip 10?

对于 10.0。 发布 9.0.2 并无初衷,我们只是作为紧急版本发布,以便在 TLS 更改生效时 Mac OS 用户不会失去对 PyPI 的所有访问权限。

@dstufft在这里做出了更充分的回应,所以我认为这已经解决了,因为它现在可能已经解决了。

我总是觉得这种“威胁”很有趣。

这根本不是威胁,如果遇到这种情况,请道歉。

这是对软件世界中经常发生的事情的观察。 人们不会按照你的承诺或意图工作。 人们使用您交付的产品。 如果您的产品具有许多人依赖的功能,那么您就不能再将其从他们的脚下拉出来。 如果你这样做了,他们就会开始认为你的产品坏了。 如果您提供的唯一解释是“好吧,无论如何我们从未承诺过”,那么他们就会开始看到您不愿意承认他们的担忧是一种责任。

这种情况发生得越多,对替代品的渴望和需求就越大。 当然,人们低估了这需要多少工作量。 但这只会使他们更有可能开始研究一个。 一旦那个球滚动,它就有了自己的生命。

替代品并不总是一件好事。 他们倾向于把事情弄得一团糟。 就个人而言,我更喜欢单个包管理器。 对于一切。 但我会满足于为 Python 提供一个包管理器。

当人们报告您破坏了某个功能时,无论是有意还是无意,请考虑简要解释为什么您必须破坏它,或者为什么保留它不可行,而不是用“这一直不支持”来消除担忧。

@dstufft ,感谢您的加入。这个线程变得非常热!

首先,我感谢您的工作! 我知道维护是一项永无止境、吃力不讨好的任务,我想当您管理一个像pip这样大而受欢迎的项目时,情况只会变得更糟!

现在,关于手头的问题:虽然到目前为止已有 20 名 _maintainers_ 报告了这个问题,但我知道这已经影响了成千上万的 _人_ - 一些受影响的项目本身就是巨大的:Anaconda、OpenStack、SpaCy、Zappa,并且有数以万计的用户。 我知道我们的 Slack 频道充斥着关于此的讨论。 (从字面上看,当我输入这个时,出现了一个新问题。)

显然,有许多重要的 Python 项目需要能够以编程方式检查其环境。 这是一件完全合理的事情,需要能够做到。 此外,该文档从未警告过不要这样做- 而且仍然没有! (单击此 repo 的 README 中的 Docs 链接!)

我认为目前的情况是:

  • 鉴于版本字符串的格式,我们都认为 pip 维护者正在遵循语义版本控制
  • pip 维护者发布了一个“补丁”,引入了巨大的破坏性变化
  • 这种变化是未经宣布和没有记录的——我认为,出乎意料和无意
  • 现在,只需调用import pip就会立即破坏一个程序,这对开发人员极为不利
  • 这引起了整个 Python 生态系统的主要问题
  • 文档没有(并且_仍然_没有 - 单击此 repo 的自述文件中的文档链接)警告不要以编程方式使用pip
  • 没有宣布import pip会在PATCH更新中造成这种损害 - 该公告是针对_尚未发布_的版本发布的。
  • 更改日志中甚至没有提到此更改
  • 我们不想替换 pip 或 pip 开发人员! 我们爱你!
  • ..但我们不希望这种事情再次发生!
  • ..所以我们确实希望遵循 semver!
  • 我们真的,真的很喜欢另一个PATCH ,它可以取消这个重大的突破性变化!

需要以编程方式检查 pip>=10.0.0 世界中的环境是另一个讨论的主题,但手头的事实是我们从未被告知我们不应该在 pip 中以编程方式使用 pip <=9 世界,并且发生了巨大的、未宣布的变化,我们真的很希望看到它逆转,因为它对成千上万的人产生了负面影响。

再次感谢,
富有的

首先:感谢 pip 维护者的努力和项目中的见解。 我相信这确实有助于其他人理解这个问题(尽管写一篇关于它的摘要博客文章可能是值得的)。

@dstufft

保持对这些事情的看法很重要。 有..少于15个? 20? 人们评论这是如何破坏他们的(尽管这些指标总是存在“冰山一角”的问题),同时 pip 9.0.2 已经是过去一周使用量第二大的安装程序(算上它甚至不存在的天数) for) 并且自发布以来已经从 PyPI 下载了 1700 万个文件。 仅从最后一天来看,它已经超过 pip 9.0.1 成为 PyPI 上最常用的安装程序的 80%。

我很确定这个指标受到来自持续集成/交付系统的所有自动化pip install pip --upgrade命令的严重影响(它们应该使用缓存,因此不需要一直从 pypi 重新安装包;但是在同时,也不应该这样做import pip ...这就是 IT 世界的运作方式)。

(少于)15 人对此​​进行了投诉,这一事实应该说明两件事:

  1. 我不认为很多人使用 9.0.2(在生产中),有些人可能仍在尝试调试这个问题,并且会通过使用 pip 9.0.1 来“临时”修复它,直到它被解决(或永远...... .) - 另外,有些人可能没有注意到某些东西还没有工作......
  2. 在发布后的 2 天内已经有人在谈论它。 更多的人会遇到这个问题。 等待 2 周,您最终可能会有 100 人抱怨它(例如,当他们完成一个 sprint 并部署到 QA/staging 时)。 在这个时间点上,你真的不知道有多少人会受到这种变化的影响。

无论如何,谈论和争论这个问题为人们提供了一个很好的例子,说明为什么永远不应该依赖内部 API,并且希望一些 3rd 方包维护者会因为这里讨论的内容而更新他们的项目。

显然,有许多重要的 Python 项目需要能够以编程方式检查其环境。 这是一件完全合理的事情,需要能够做到。 此外,该文档从未警告过不要这样做 - 而且仍然没有! (单击此 repo 的 README 中的 Docs 链接!)

我不清楚你为什么要对此提出警告。 将pip用作除命令行工具以外的任何工具完全没有记录。 搜索文档我根本没有看到任何关于导入 pip参考。 这就像抱怨,因为您链接了 Chrome 使用的一些.so ,它们破坏了 ABI 兼容性。

SemVer 的通常解释是它适用于受支持公共接口(在本例中为 CLI),而不是未记录的内部。 任何使用内部组件的人都应该固定他们的pip版本,因为它们可能会被任意更改。

真的没有什么可以逆转的。 向后移植修复以防止 macOS 上的大量用户在不久的将来无法访问 PyPI,当应用于 9.0.x 代码库时存在一个错误,该错误似乎仅在不受支持的条件下表达。 唯一的前进道路是做额外的工作来解决 9.0.x 系列中的那个错误。 就像我说的,如果我能找到时间,我会尝试去做,如果你想增加它发生的机会,那就提供一个补丁。

该文档没有警告它,因为无法提供您可以使用 pip 执行但不受支持的操作的详尽列表。 相反,我们依靠相当普遍的方法来记录受支持的内容,并且任何未记录的内容都应假定为不受支持(如果您想依赖未记录的内容,请打开一个问题,要求将其记录在案并因此得到支持)。

从长远来看,我们可能会转向基于日期的发布方案,以(希望)消除关于我们是否是 semver 的任何混淆。

从我的iPhone发送

2018 年 3 月 20 日上午 11:02,Rich Jones [email protected]写道:

@dstufft ,感谢您的加入。这个线程变得非常热!

首先,我感谢您的工作! 我知道维护是一项永无止境的、吃力不讨好的任务,我想当你管理一个像 pip 这样大而受欢迎的项目时,情况只会变得更糟!

现在,关于手头的问题:尽管到目前为止已有 20 名维护者报告了这个问题,但我知道这已经影响到了成千上万的人——一些受影响的项目本身就是巨大的:Anaconda、OpenStack、SpaCy、Zappa 和数以万计的用户。 我知道我们的 Slack 频道充斥着关于此的讨论。 (从字面上看,当我输入这个时,出现了一个新问题。)

显然,有许多重要的 Python 项目需要能够以编程方式检查其环境。 这是一件完全合理的事情,需要能够做到。 此外,该文档从未警告过不要这样做 - 而且仍然没有!

我认为目前的情况是:

鉴于版本字符串的格式,我们都认为 pip 维护者正在遵循语义版本控制
pip 维护者发布了一个“补丁”,引入了巨大的破坏性变化
这种变化是未经宣布和没有记录的——我认为,出乎意料和无意
现在,只需调用 import pip 就会立即中断一个程序,这对开发人员极为不利
这引起了整个 Python 生态系统的主要问题
该文档没有(并且仍然没有 - 单击此 repo 的自述文件中的文档链接)警告不要以编程方式使用 pip。
在 PATCH 更新中没有宣布 import pip 会造成这种损害 - 该公告是针对尚未发布的版本发布的。
更改日志中甚至没有提到此更改
我们不想替换 pip 或 pip 开发人员! 我们爱你!
..但我们不希望这种事情再次发生!
..所以我们确实希望遵循 semver!
我们真的,真的很喜欢另一个补丁,它可以取消这个重大的突破性变化!
需要以编程方式检查 pip>=10.0.0 世界中的环境是另一个讨论的主题,但手头的事实是我们从未被告知我们不应该在 pip 中以编程方式使用 pip <=9 世界,并且发生了巨大的、未宣布的变化,我们真的很希望看到它逆转,因为它对成千上万的人产生了负面影响。

再次感谢,
富有的


你收到这个是因为你被提到了。
直接回复此电子邮件,在 GitHub 上查看它,或将线程静音。

@Miserlou

鉴于版本字符串的格式,我们都认为 pip 维护者正在遵循语义版本控制

作为一个强烈反对 semver 的人,能否告诉我我的版本字符串应该采用什么格式来消除这种混淆? “三个虚线数字”对我来说并不意味着“严格遵循 semver”,所以这个假设令人惊讶。

对此评论的回应:无论 pip 是否遵守 semver 或承诺遵守它, major.minor.micro版本控制方案的使用仍然隐含承诺对微版本进行某种限制。 如果像~= 9.0.1这样的兼容发行版引脚不足以保护用户免受向后兼容性的意外中断,那么唯一安全的替代方案就是普通版本匹配。 如果不打算支持版本匹配以外的任何东西,那么 pip 还不如切换到只有一个单调递增组件的 Chrome 风格的版本方案。

编辑:我看到@dstufft已经提议通过采用基于日期的版本朝这个方向发展。 我认为这将是这起事件造成的不幸的附带损害。

所以是的,作为志愿者驱动的软件项目的用户,我们需要平衡我们的期望和对用户/维护者关系性质的欣赏。 同样清楚的是,这个版本并不是为了让import pip突然开始失败。 但另一方面,我认为人们对在微版本中发生的这种回归感到沮丧是合理的,而发布修复该问题的 9.0.3 版本似乎是一种合理的补救措施。

顺便说一句,我可以通过以下步骤在 virtualenv(2 或 3,没关系)中重现它:

virtualenv -p python3 /tmp/pip
/tmp/pip/bin/pip install -e path/to/clone/of/pip/9.0.2
/tmp/pip/bin/pip install requests
/tmp/pip/bin/python

然后,在 python shell 中:

>>> import requests
>>> import pip

如果还没有导入请求,则import pip成功。

向后兼容性的意外中断

请告诉我import pip在哪里被记录为符合我们做出的向后兼容性承诺的稳定 API? 我想确保删除此类文档,因为我们坚决不支持这种使用。

除非您认为绝对没有任何东西可以破坏,即使是不受支持、未经测试的用途。 在这种情况下,您可能想要固定== ,因为此时您可能正在使用的所有内容完全不可知,并且每个更改都可能成为某人的重大更改(强制性xkcd )。

pip是 Python 的包管理器。 Python 是一种编程语言。 人们需要以编程方式检查他们的环境。 1+1=2。

人们认为这是正确的做法是完全合理的。 没有 - 并且仍然没有_ - 文档中的任何内容都说 _not_ 这样做。 提醒一下,有超过 700,000份申请得出了同样的结论! 另外-没有其他方法可以做到!

仅仅因为某些内容没有在 ReadTheDocs 中记录并不意味着它是被禁止的——我们每天都会遇到和使用仅以这种方式提供代码的项目。

如果有的话, pip甚至 _has_ 一个命令行界面这一事实似乎很好地表明它可以用作一个库,因为它已经有一个 Python 客户端!

此外,我们不是在谈论使用_命名空间的私有 API,按照惯例,或者甚至是任何特定的公共方法,我们只是在谈论导致这种灾难性失败的 _just 调用 import_ 。

文档中没有 - 现在仍然没有 - 任何内容说不要这样做。

https://pip.pypa.io/en/latest/user_guide/#using -pip-from-your-program

如果您单击_this very repo_ 的“文档”链接,您将无法访问该页面。 没有人参考最新的。 您自己的文档链接不会链接到最新的。 无法访问该页面。 一切都趋于稳定,其中不包括该部分。

@Miserlou我认为对于那些以某种方式认为他们应该导入命令行工具的内部结构的人来说,这是一种善意,因为它恰好是在Python中实现并且这些内部结构是可导入的。

我知道您对pip的公共界面的理解与我、开发人员和大多数将pip视为 CLI 程序的人不同,但这样做的实际危害是什么? 只需固定pip != 9.0.2并完成它。

很明显,在这一点上,我们都在同一个页面上,什么是受支持的公共 API 的一部分,哪些不是,现在没有什么可以做的,以某种方式追溯让每个人都注意到。

老实说,pip 的维护者已经表示,如果时间允许,他们会尝试修复这个问题,尽管鼓励每个人提交 pull request 以加快速度。

我认为目前我们所能做的就是让 3rd-party 库意识到这个问题,并将它们指向这个问题。 无论如何,长期的第 3 方库都需要解决这个问题,并且希望它们不使用import pip而是通过命令行调用 pip(使用 subprocess 或类似的 python 命令)。

我相信这个讨论不太可能有成效,也没有什么要说的。 有:

  • 对问题的充分描述。
  • 如果有人遇到它,他们可以采用的可能的解决方法。
  • 根据我们的向后兼容性指南,为什么我们不认为这是一项重大更改的理由。
  • 我将尝试找时间修复它的声明(尽管没有关于它的承诺)。
  • 如果受此影响的人想让9.0.3更可能存在于修复程序中,则可以采取行动呼吁。

在这一点上,讨论没有真正的目的,除了进一步挫败所有相关人员,所以我现在退出这个问题。 此问题将在 10.0 或 9.0.3 发布时关闭。 如果有人确实为行动呼吁付出了努力,欢迎他们打开拉取请求,或提交关于此问题的差异。

为了让这个 do-not-import-pip 口头禅更加明显,将命名空间重命名为“_pip”怎么样。 这表明整体在名称级别上不供公众使用。
此外,告诉自动检查代码不要查看以下划线开头的内容会更容易。 好吧,后者也需要更改参与检查代码。 但至少有机会在不管理黑名单的情况下通过它(按照惯例)实现自动化。

好的,我发誓的最后一件事 - pip 10 已经将所有相关代码移动到pip._internal (我们没有使用_pip因为这会破坏python -m pip ,这是受支持的)。

谁能验证https://github.com/pypa/pip/pull/5100是否为他们解决了这个问题?

从头开始,我认为#5100 是错误的,请您验证一下https://github.com/pypa/pip/pull/5101

@dstufft我可以确认,#5101 中的修复解决了我的问题。

感谢@dstufft 抽出时间解决这个问题。 我将与 Anaconda 团队一起沟通这个问题,并帮助他们摆脱导入 pip。

对于此线程中的记录,#5101 也解决了我的问题。

同上,#5101 允许导入在我们的工具中工作。 警告购买者:我没有广泛测试修补的 pip 和我们的工具。

这应该在 9.0.3 中修复。

感谢一个从未写过import pip的人提供的快速解决方案,但他们是这样做的包裹的消费者。 在阅读完这个帖子之后,听起来很多应用程序已经导入了 pip,但在不知不觉中违反了最佳实践,并且许多开发人员和用户可能会受到 v9.0.2 和 v10 的影响。

我第二次/第三次/第 N 次添加了适当的弃用警告以使事情更顺利。 甚至可能是 pypi.python.org 帖子?

万岁! 谢谢你!

我也非常喜欢弃用警告,更重要的是 - 关于如何以编程方式检查 pip10 世界中的 python 环境的正确说明! 鉴于超过 700,000 个应用程序受到此错误的影响,显然需要这样做。

pip list --format=json ?

首先感谢所有为 pip 做出贡献的人,因为它完全涵盖了我所有的用例,并带有一些用户友好的选项和参数。

由于这种“令人惊讶地被广泛采用和有用的未定义行为” ,我们是否需要将 piplib 作为 git 的 libgit2? 请注意,libgit2 不与 git 共享任何代码,而是由 git 的其他组维护。 它对 git 生态系统有好处。 也许 piplib 会涵盖一些我们没想到的有趣用例。

这是一个类似的故事: https ://public-inbox.org/git/1267957655.3759.29.camel@mattotaupa/T/

@drunkwcodes我怀疑您的建议已经在 pip 文档提到的现有软件包中实现, packagingsetuptoolsdistlib 。 据我从这个线程中可以看出,功能上的差距没有问题,但有些人对尝试导入和检查每个模块的工具有问题,并将导入失败视为致命错误。

在我看来,这些工具可以通过将 import 语句包装在 try/except 块中来解决这个问题,但这似乎也是一个值得商榷的先例。 不过,鉴于 pip 9.0.3 的发布,我认为可能不值得花时间讨论导入问题,除非问题在 pip 10 中再次发生。无论如何,只要维护者不竭尽全力import pip失败,或直接拒绝修复此类失败的补丁,会有共同的立场。

@sruggier 提到的包都很好,而且WheelFile.install()也需要更多的推广。 但pip.main()所提供的一站式服务是以上所有不可替代的。 还是值得一试的。

最重要的是,我希望这些需求由另一个项目来持有,并且 pip10 能够顺利到达,无需额外的保证。 弃用和最小化代码库是主要版本的重点。

永久性基础设施“软件”的具体实施细节是荒谬的。 您不能通过记录在案的滥用案例来判断维护者并阻止 pip 的轮子。

如果您坚持使用 pip 作为库,则需要重新考虑许多假设。

@drunkwcodes为了清楚起见, pip.main()是最容易替换的用法 - 您只需要使用subprocess.run([sys.executable, '-m', 'pip', <rest of args>])

另外, WheelFile.install()没有被提升的原因是 wheel 项目还声明他们不提供用户可见的 API - 我们最初在 pip 文档中提到了 wheel,但应他们的要求将其删除。 不过,车轮 PEP 非常清楚如何安装车轮 - 在 3rd 方模块中实施并不难。

我很欣赏你们在 pip 上所做的工作,并且知道这并不容易。 但为了记录:

我有点失望,人们还没有离开 import pip。 受此问题影响的人仍然需要为 pip 10 做准备

spaCy远离import pip 。 但是有些人仍在使用 spaCy 1,它确实导入了 pip --- 并且出于显而易见的原因,没有将 pip 固定到补丁版本中。 如果在 v10 中进行了更改,我们的旧版本就不会受到影响。 我们刚刚发布了一个修补程序来解决这个问题。

关于如何以编程方式检查 pip10 世界中的 python 环境的正确说明

PyPA 在 distlib 上的立场是什么? Pip 显然以某种方式使用它,但它也使用打包,distlib 声称要弃用它。

如果没有官方立场,那么至少 pip 核心维护者的当前想法和意见将不胜感激。 如果其他地方有关于这个话题的相关讨论,一个简单的指向其他讨论的指针对我来说已经足够了。

我不知道 distlib 不赞成打包。 它提到了“distutils2/packaging”,但 distutils2 有所不同。

我个人的观点是 distlib 和包装都是完全合理的使用方法。 您应该自己评估它们以确认它们满足您的需求,显然,就像您依赖的任何其他依赖项一样。

也许贬低这个词太强烈了。 我目前理解的来源:

https://distlib.readthedocs.io/en/latest/overview.html#distlib -evolved-out-of-packaging

啊,这是一个不同的“包装”——它是提议的 stdlib 模块,旨在取代 distutils。 它与 PyPI packaging项目完全不同。 可能值得让 distlib 项目更好地澄清这种区别。

可能值得让 distlib 项目更好地澄清这种区别。

已经这样做了:) 请参阅: https ://bitbucket.org/pypa/distlib/issues/100/clarify-project-positioning-and-status

该线程已被自动锁定,因为它关闭后没有任何最近的活动。 请为相关错误打开一个新问题。

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