在最近与同事的一次对话中,我们讨论了锁定"是否是最佳做法。或者在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中发生重大变化,这将破坏我们的模块。锁定相当特定版本的依赖项是否合理?
我认为,虽然依赖可以很好地破坏我们的代码,但编写这些依赖关系的人会考虑很多,如果有什么东西可以打破它,那么降级到无论如何,一个工作版本。而且我没有看到他所建议的那种限制性模型。这有什么理由吗?
答案 0 :(得分:2)
有了这个:
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'
锁定时需要考虑多个方面:
优选地,对于改变包的主要,次要和微/构建/修订号的含义,存在预定义的语义。如果更改包的主版本号被定义为可能破坏某些内容的API更改,则不修复(即仅使用>=
)将会破坏某些内容。
每个包的这些语义都不相同。特别是如果主要版本为0,则包可能仍会更改,您可能希望修复次要版本号(例如,使用0.3。*,或者使用pip:>=0.3,<0.4
)
如果您有多个依赖项,并且依赖项彼此依赖,则可能具有非重叠锁定要求。例如。您指定pyserial 2.7.*
和some.package 0.4.*
,然后some.package
需要pyserial 2.5.*
如果您有适当的测试覆盖率,您应该能够发现某个软件包的新版本是否会破坏您的“构建”。然后,它取决于纠正它是多么容易(例如,找到这种包的最后一个工作版本)以及是否可以及时完成。如果您在自己的软件中有一个紧急错误修复,并且由于您没有锁定而导致部署延迟,现在必须花时间找到罪魁祸首包并将其锁定,这可能是不可接受的。
在选择其他软件包时,您可能需要修复所有错误,而不需要兼容性。另一方面,如果您有适当的测试覆盖率,那么您应该已经找到了您所依赖的所有软件包中可能存在的所有错误,这是对特定版本进行“紧密”锁定的一个参数。
如果您依赖的软件包本身没有或者测试覆盖率很低,并且/或者在微/版本号更改方面具有突破性的声誉,您可能希望完全锁定它。
实际上最好的,往往取决于以上所有。如果你不能处理部署延迟 - 弄清楚包错误的哪个小版本 - 你必须锁定。但是,如果您的包依赖树很复杂,您可能必须放宽限制才能安装所有包。
最重要的是要知道你正在做的后果。对复杂项目进行严密锁定可能需要相当长的时间才能找到包的“允许”版本号范围,只需确保您有时间被迫更改它。
所以是的,可能有理由让你的同事建议严密锁定。但是,在您的情况下是否有必要取决于上述所有因素。