conda meta.yaml 中的 "locking" 要求是个好主意吗?

Is "locking" requirements in conda's meta.yaml a good idea?

在最近与一位同事的谈话中,我们讨论了 "lock" 或在 meta.yaml 文件中指定某个主要版本是否是最佳实践,如下所示:

requirements:
  build:
    - python 3.5.*
    - pyserial 2.7.*
  run:
    - python 3.5.*
    - pyserial 2.7.*

而不是...

requirements:
  build:
    - python >=3.5
    - pyserial >=2.7
  run:
    - python >=3.5
    - pyserial >=2.7

据我所知,他担心的是 pyserial 的开发人员,例如,可能会在 3.0 版中做出重大更改,这会破坏我们的模块。这种担忧是否有理由锁定相当特定的依赖版本?

我认为虽然依赖项 可能 很可能会破坏我们的代码,但编写这些依赖项的人正在考虑很多,如果有什么东西应该破坏它会无论如何降级到工作版本都是微不足道的。而且我还没有看到像他建议的那样的限制性模型。这有什么原因吗?

有了这个:

requirements:
  build:
    - python 3.5.*
    - pyserial 2.7.*
  run:
    - python 3.5.*
    - pyserial 2.7.*

您没有锁定主要版本,而是锁定次要版本,锁定主要版本需要:

requirements:
  build:
    - python 3.*.*
    - pyserial 2.*.*
  run:
    - python 3.*.*
    - pyserial 2.*.*

(或者可能只有一个 * 而不是 *.*)。

这种锁定等同于使用 >=< 在次要版本号上使用 pip 安装时:

pip install 'some.package>=0.14.0,<0.15'

或主要版本号:

pip install 'some.package>=0.0,<1.0'

锁定时需要考虑多个方面:

语义

最好有关于更改包的主要、次要和 micro/build/revision 编号的含义的预定义语义。如果更改包的主要版本号被定义为可能破坏某些东西的 API 更改,那么 not 修复(即仅使用 >=)将破坏某些东西.

每个包的这些语义都不相同。特别是如果主要版本为 0,包可能仍会更改,您可能希望修复次要版本号(例如使用 0.3.*,或在 pip 中:>=0.3,<0.4)

您的依赖项的复杂性

如果您有多个依赖项,并且这些依赖项相互依赖,您可能有非重叠锁定要求。例如。您指定 pyserial 2.7.*some.package 0.4.* 然后 some.package 需要 pyserial 2.5.*

您多久能发现破损,修复它有多容易

如果您有适当的测试覆盖率,您应该能够查明某些软件包的新版本是否破坏了您的 "build"。然后,这取决于更正它的难易程度(例如,找到此类包的最后一个工作版本)以及是否可以及时完成。如果您在自己的软件中有一个紧急错误修复,并且由于您没有锁定而延迟部署,现在不得不花时间找到罪魁祸首并将其锁定,这可能是不可接受的。

如果你没有最新版本你会失去什么

在选择另一个软件包时,您可能需要所有错误修复而不是不兼容问题。另一方面,如果您有适当的测试覆盖率,您应该已经发现了您所依赖的所有包中可能存在的所有错误,这是 "tight" 锁定特定版本的论据。

所选锁定范围内破损的几率

如果您所依赖的软件包本身没有或几乎没有测试覆盖率,and/or 以在 micro/build 版本号更改时收支平衡而闻名,您可能想要锁定它完全下降。


通常情况下,实际上最好的方法取决于以上所有因素。如果你不能处理部署延迟——弄清楚包在哪个次要版本上出错——你必须锁定。但是,如果您的包依赖关系树很复杂,您可能必须放宽限制才能安装所有包。

所有这一切中最重要的是知道你正在做的事情会产生什么后果。对复杂项目的紧密锁定可能需要相当长的时间才能找到包的 "allowed" 版本号范围,只要确保你有时间被迫更改它即可。

所以是的,您的同事建议的紧密锁定可能是有原因的。但在您的情况下是否有必要取决于上述所有因素。