tox环境下pip --editable参数不受顺序影响被覆盖的问题
我之前也踩过这个坑,本质是pip的依赖解析逻辑在起作用:当你同时指定了一个包的可编辑安装(--editable)和版本约束(比如some_dep>=0.1.2)时,pip不会严格按照命令行的安装顺序执行,而是会根据版本优先级重新评估依赖。如果你的本地可编辑包版本号不满足requirements.txt里的约束,pip就会自动去PyPI下载符合要求的正式版本,直接覆盖掉你的可编辑安装——哪怕你把--editable放在deps的最前面也没用。
下面是几个实用的解决办法,按推荐程度排序:
1. 让本地可编辑包的版本号满足requirements约束
最省心的办法就是修改你本地some_dep包的版本号,让它符合>=0.1.2的要求。比如在some_dep的setup.py或者pyproject.toml里,把版本号改成0.1.2,或者带dev后缀的0.1.3.dev0(pip会把dev版本视为满足>=0.1.2的)。
这样一来,当pip处理requirements.txt的约束时,会发现本地可编辑的版本已经达标,就不会多此一举去PyPI下载覆盖了。
2. 用约束文件替代直接在requirements里写版本
如果不想改本地包的版本号,可以用pip的**约束文件(constraint file)**来处理版本要求,同时保留可编辑安装的优先级。
修改你的tox.ini配置:
[testenv] usedevelop = True deps = --constraint=requirements.txt --editable=file:///{toxinidir}/../some_dep
--constraint的作用是告诉pip:所有依赖必须满足requirements.txt里的版本规则,但不会自动安装这些依赖。这样你先指定可编辑安装的some_dep,pip会检查它是否符合约束,只要符合就会保留,不会去PyPI拉新包。
这种方法既保留了requirements.txt的版本管理作用,又确保了本地可编辑包的优先级。
3. 给可编辑安装加--force-reinstall强制优先级
如果你必须保持requirements.txt的内容不变,也可以试试给可编辑安装加上--force-reinstall参数,强制pip先安装本地版本:
修改tox.ini:
[testenv] usedevelop = True deps = --editable=file:///{toxinidir}/../some_dep --force-reinstall --requirement=requirements.txt
不过这个方法要谨慎使用,因为--force-reinstall会强制重新构建安装可编辑包,增加测试环境的搭建时间,而且如果requirements里有其他依赖冲突,可能会引发意想不到的问题。
4. 升级pip到最新版
旧版本的pip依赖解析器可能存在逻辑bug,导致顺序处理不符合预期。升级到最新版的pip(比如23.x及以上),新的resolver逻辑会更合理,能更好地处理可编辑依赖和版本约束的关系。
你可以在tox.ini里先指定升级pip:
[testenv] usedevelop = True deps = pip>=23.0 --editable=file:///{toxinidir}/../some_dep --requirement=requirements.txt
总的来说,方案1和方案2是最稳妥的,既能保持依赖管理的清晰,又能彻底解决覆盖问题。
内容的提问来源于stack exchange,提问作者mnowotka

