如何解决私有Python包与公共包重名的pip安装问题,并将所有依赖上传至devpi私有索引
嘿,这个重名问题确实挺闹心的——我之前也碰到过类似的情况,pip不分青红皂白就去拉公共包,完全忽略了我的私有版本。下面给你几个可行的解决方案,重点说你提到的「把所有依赖上传到devpi」的思路,也给你一些更省心的替代方案:
方案一:直接利用pip索引优先级(不用上传所有依赖,最快解决重名)
你当前用的pip install --index-url <你的私有索引> --extra-index-url https://pypi.org/simple/命令,其实新版本pip(20.3+)会优先从--index-url指定的主索引找包,只有主索引找不到的依赖才会去--extra-index-url拉。那为什么还会安装公共重名包?大概率是这两个原因:
- 你的pip版本太旧,旧版本pip会从所有索引里找最新版本的包,不管索引优先级;
- 你的私有索引里没有你要安装的包的对应版本(比如你只传了
0.1.0,但安装时没指定版本,公共索引里的1.0.0被当成了最新版)。
解决步骤:
- 先升级pip到最新版本:
pip install --upgrade pip - 安装时如果需要指定版本,明确写出来:
pip install --index-url <你的私有索引> --extra-index-url https://pypi.org/simple/ your-package==0.1.0 - 如果不想指定版本,确保你的私有索引里的包版本是你想要的最新版,这样pip会优先从主索引拉你的私有包,依赖还是正常从公共索引获取。
方案二:把所有依赖上传到devpi私有索引(实现完全离线/私有环境)
如果确实想把所有依赖都放到私有索引里,彻底脱离公共pypi,步骤如下:
1. 下载项目所有依赖到本地
首先,把你的项目直接依赖和间接依赖都下载下来:
- 如果有
requirements.txt,用这个命令:pip download -r requirements.txt -d ./local-deps - 如果只有
setup.py,可以直接下载当前项目的所有依赖:pip download . -d ./local-deps
这个命令会把所有需要的包(比如NumPy、你的私有包依赖的其他公共包)都下载到./local-deps目录里。
2. 上传依赖到devpi
先确保你已经登录了devpi,并且切换到了你的私有索引:
# 登录devpi(替换成你的用户名和密码) devpi login your-username --password your-password # 切换到你的私有索引(比如你的索引地址是http://your-devpi-server/your-username/your-index) devpi use http://your-devpi-server/your-username/your-index
然后批量上传本地的依赖包:
devpi upload --from-dir ./local-deps
如果碰到相同版本的包已经存在的情况,可以加--force参数强制覆盖:
devpi upload --from-dir ./local-deps --force
3. 安装你的包(无需额外索引)
现在所有依赖都在你的私有索引里了,安装时只用指定你的私有索引即可:
pip install --index-url <你的私有索引> your-package
这样pip只会从你的私有索引找包,完全不会去公共pypi,自然就不会碰到重名问题了。
方案三:用devpi镜像缓存依赖(更省心的折中方案)
手动上传所有依赖有点麻烦,其实devpi支持继承官方pypi的镜像,这样依赖会自动缓存到你的私有索引里,同时你的私有包优先级更高,完美解决重名问题:
1. 创建/修改你的私有索引,继承pypi镜像
登录devpi后,修改你的索引,让它继承官方pypi的镜像:
# 假设你的索引名为your-index,修改它的bases为/root/pypi(devpi默认的pypi镜像) devpi index modify your-index bases=/root/pypi
如果是新建索引的话:
devpi index create your-index bases=/root/pypi
2. 上传你的私有包到这个索引
在你的项目目录下,执行:
devpi upload
这样你的私有包就传到了自己的索引里。
3. 安装你的包
安装时只用指定你的私有索引:
pip install --index-url <你的私有索引> your-package
此时,pip会先在你的私有索引里找包:
- 你的重名包在私有索引里,优先安装你的版本;
- 如果是依赖包(比如NumPy),私有索引里没有的话,devpi会自动从官方pypi拉取并缓存到你的索引里,下次安装就不用再去公共pypi了。
这个方案既解决了重名问题,又不用手动上传所有依赖,是我个人比较推荐的做法。
备注:内容来源于stack exchange,提问作者ryuzakinho




