使用 pip 安装软件包的多个版本
- 2025-04-16 08:56:00
- admin 原创
- 15
问题描述:
在我的应用程序中我想使用:
packageA
,这需要packageX==1.3
packageB
,这需要packageX==1.4
packageX==1.5
我该如何使用packageX
pip 安装多个版本来处理这种情况?
解决方案 1:
pip
不会帮助你。
你可以指定安装特定版本,但它会覆盖另一个版本。另一方面,使用两个虚拟环境可以让你在同一台机器上安装两个版本,但不能同时使用它们。
最好的办法是将两个版本以不同的名称放入 Python 路径中,手动安装它们。
但是如果你的两个库希望它们具有相同的名称(它们应该如此),你将必须修改它们,以便它们使用一些导入别名来选择它们所需的版本,例如:
import dependencyname_version as dependencyname
目前还没有简洁的方法来实现这一点。你所能做的最好的就是祈祷这个 hack 能够成功。
我宁愿放弃这两个库中的一个并用等效的库替换它,或者修补它以接受新版本的依赖项并将补丁返还给社区。
解决方案 2:
下载每个软件包的源代码。每个软件包都安装在各自的文件夹中。例如,我有一个 1.10 版本的软件包,但想切换到 dev 版本进行一些工作。我下载了 dev 模块的源代码:git clone https://github.com/networkx/networkx.git
cd netwokrx
我为此版本创建了一个文件夹:
mkdir /home/username/opt/python
,然后将 PYTHONPATH 环境变量设置为:export PYTHONPATH=/home/username/opt/python/lib/python2.7/site-packages/
。接下来,我使用以下命令安装它:python setup.py install --prefix=/home/username/opt/python
现在,由于我的 PYTHONPATH 指向了另一个 site-packages 文件夹,当我在命令行中运行 python 并导入新模块时,它就可以正常工作了。要切换回原样,请从 PYTHONPATH 中删除新文件夹。
>>> import networkx as nx
>>> nx.__version__
'2.0.dev_20151209221101'
解决方案 3:
我在 Blender 中使用 Python 时,一个不太好用的解决方法是安装(并保持在路径之外)一个类似版本的 Python,然后使用 subprocess 让另一个版本完成所需的工作。如果你除了安装 pandas 和 scipy 之外还做了其他事情,Blender 的 Python 往往会变得有点不稳定。我尝试过在 Blender 中使用虚拟环境,但这往往会破坏程序。
另外,如果您偶尔使用 Blender 进行数据可视化,则需要在版本号文件夹中添加一个配置文件夹,这样可以保存所有插件,使其更易于移植,并且更不容易干扰其他 Blender 的安装。许多为 Blender 制作插件的人并非“程序员”,所以这些精明的人经常会做一些非常 hack 的事情,而这是我能用过的最佳解决方法。
另一个解决方法(这个方法在运行过程中有太多的 flags,应该让我没资格碰键盘)是手动找到init文件,然后用 importlib 手动将其添加到全局变量中……但这是有风险的。有些模块这样做可以正常运行,但其他模块可能会抛出一些错误,导致需要额外的特殊故障排除会话。保持版本一致确实可以减少问题,我用这个方法从虚拟环境导入模块时运气还不错,但我使用 Blender 的 Python 时使用子进程调用是有原因的。
def importfromfilelocation(x,y,z):
#"""x = 'tk',y = "tkinter", z =r'C:pyth"""
mod_alis = x
spec = importlib.util.spec_from_file_location(y, z)
print(spec)
mod_alis = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod_alis)
globals()[str(x)]= mod_alis
解决方案 4:
每次我需要更新旧的 python 库时,我都会执行以下操作:
克隆我需要更新的库(通常从 GitHub 克隆)
运行 git checkout 到我当前正在使用的版本
在某些软件包存储库(对我来说通常是 Gemfury)中使用不同的名称打包旧版本
使用我指定的新名称安装旧版本
将软件包更新到我想要使用的新版本
如果新版本失败,请创建一个回退版本 - 回退到旧版本
代码看起来是这样的:
import ujson # ujson version 5.7.0
import ujson_old # ujson version v1.34
ujson_dumps(some_obj: Any) -> str:
try:
return ujson.dumps(some_obj)
except ValueError:
logging.error('Error parsing with new ujson version')
return ujson_old(some_obj)
我建议阅读这篇博客文章,了解 ujson 如何从非常旧的版本升级到最新版本
解决方案 5:
另一个“解决方法”是使用 IPC/RPC 并在服务中运行独立的包。如果依赖项位于不同的库上,则可以根据包的使用情况进行区分。
扫码咨询,免费领取项目管理大礼包!