Python 第三方依赖引发的惨案

最近要再复现一下论文的实验结果作为最后的检查,由于服务器重装导致原本配置的conda环境丢失,所以我需要重新配置。 本来想着在前几个月写代码的时候已经做好了requirements.txt,直接安装就好了,然而并没有这么顺利,在多处排查(数据集,代码,环境)之后才发现真正的原因来自第三方依赖。

其中我的程序最核心的依赖是 angr,版本为 9.2.36,requirements.txt 如下:

angr==9.2.36

安装之后当然 angr 的版本是符合预期的,但实验结果却很奇怪,简单来说就是得到的中间表示和预期不符,少了一些信息。我一开始还以为是不是数据集在这个诡异的服务器重装时出现了问题或者是我错误的更改了代码。而在和我另一台电脑的环境比对之后,最终发现是 angr 的依赖 capstone 的版本不一致导致的,从 5.0.1 换成 4.0.2 之后就一切正常了。

那么为什么会出现这一问题呢,我查看了对应版本下 angr 的依赖,发现了这么一段:

capstone!=5.0.0rc2,>=3.0.5rc2

原来 angr 只要求不是 5.0.0rc2 且大于 3.0.5rc2 的版本,有可能开发者已经发现了 5.0 版本的 capstone 并不兼容所以特地排除。在我当初做实验的时候,在这个约束下会使用 4.0.2 的 capstone。然而到现在,capstone 已经有更新的 5.0.1 了,因此我们就会装目前最新的版本,但是 9.2.36 的 angr 并不兼容 5.0.1,最终导致实验不符合预期。而为了避免这一问题,我们只需要在 requirements.txt 中指定 capstone 的版本即可。

没想到即使写了 requirements.txt 锁住了我直接依赖的库的版本,还是因为依赖的依赖的版本踩了一个大坑 :(

本来我对于依赖这一问题是不太在意的,现在看来依赖冲突检测还是相当有意义的,即使我这种小型代码随着时间的推移也有可能出现这种难以发现的依赖问题,更不用说大型项目了。不过从技术角度来说,想要自动化的检测这种依赖冲突是相当困难的,运行时并不会有直接的异常产生。 怪不得我前几周看到的论文都是从论坛和各种地方爬取讨论的信息构建依赖冲突的知识图谱然后再进行检测的,想要检测出我面对的这种问题,使用一些简单的基于源码的依赖分析确实相当困难。