V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
huluhulu
V2EX  ›  Python

Python 依赖库的引用问题,感觉没有合适的方法

  •  
  •   huluhulu · 322 天前 · 1723 次点击
    这是一个创建于 322 天前的主题,其中的信息可能已经有所发展或是发生改变。
    总结来说,就是下面的引用关系:
    项目 A 引用了开源代码 B 和 C 库,但是 B 用了 D 的 1.1 ,C 用了 D 的 2.0.
    D 的 1.1 和 2.0 接口不兼容

    怎么解决这个问题?感觉现有的 venv 解决方案都是为了不同开源库的隔离,而不是实现开源库之间的并存。

    是不是目前最好的方法,只能自己修改 B 和 C ,让他们调用同一个版本的 D ?
    18 条回复    2023-07-07 16:51:46 +08:00
    alexsz
        1
    alexsz  
       322 天前
    修改 B 适配新版 D
    tabris17
        2
    tabris17  
       322 天前
    Dependency hell
    如果版本冲突实在无法解决,只能拆成两个项目,或者在 B 和 C 舍弃其中一个
    huluhulu
        3
    huluhulu  
    OP
       322 天前
    很多 tensorflow 的开源代码,依赖版本要求特别严格。如果真要适配,需要很多改动,没办法开箱即用了。
    头疼。
    llh880808
        4
    llh880808  
       322 天前
    可以考虑使用 monkey patch

    在模块 A 中重新实现 b 中的 call_foo 方法,就不会报错了

    (记得空格会被吞,以下用.代替行首空格了)

    ```python
    # file a.py
    import b
    import c

    from d import foo

    def call_foo():
    ....# 重新实现 call_foo 方法
    ....foo(3, 4, 5)

    # 修改 b 的 call_foo 方法
    b.call_foo = call_foo

    b.call_foo()
    c.call_foo()

    # file b.py
    from d import foo

    def call_foo():
    ....# 模拟调用 1.x 版本 d.foo(),传两个参数
    ....foo(1, 2)

    # file c.py
    from d import foo

    def call_foo():
    ....# 模拟调用 2.x 版本 d.foo(),传三个参数
    ....foo(1, 2, 3)

    # file d.py

    # 模拟实现 2.x 版本 d.foo(),必须传三个参数
    def foo(a, b, c):
    ....pass
    ```
    lisongeee
        5
    lisongeee  
       322 天前
    如果是 js + pnpm 就没有这个问题,js 的依赖管理机制 天然支持 单个库的 多版本共存
    lrigi
        6
    lrigi  
       322 天前 via iPhone
    你能不能把两个 D 保存到本地文件夹,然后重命名为 D1 ,D2 ,然后分别引用各自的 D 就行了?
    chenzi0103
        7
    chenzi0103  
       322 天前
    可以试一下 poetry
    Syiize
        8
    Syiize  
       322 天前 via Android
    简单的方法就是将旧版本 D 包更名后安装,然后修改 B 使其使用旧版本的 D
    bestcondition
        9
    bestcondition  
       322 天前 via Android
    我想问下 op 主遇到的具体是哪两个库有依赖冲突呢?
    ClericPy
        10
    ClericPy  
       322 天前
    一开始想的是

    pip install a==1.0 -t ./a1

    pip install a==2.0 -t /a2

    sys.path.extend(['./a1', './a2'])

    后来一想, 实际没用. 遇到过, 强行升级/降级 解决的, 解决不了的走 RPC 了, 坑爹
    hsfzxjy
        11
    hsfzxjy  
       322 天前   ❤️ 2
    如果是 tensorflow 冲突,前面说的应该都不奏效。只要同一个进程里存在两个版本的 tensorflow 极大概率会出问题,因为 tf 有很多 native 的代码,怎么改名都没用

    如果对于 B 和 C ,你只是把他们当黑箱来应用,即只是简单地直接喂数据给 B 和 C 得到结果,有一个办法是把他们服务化。首先你分别为他们创建他们自己的 venv ,然后分别用两个 venv 的 python 起两个进程,你的主进程使用 IPC 和他们通信即可。
    inhzus
        12
    inhzus  
       322 天前
    楼上 +1 ,额外多起一个服务,本地 IPC 通信好了
    wxf666
        13
    wxf666  
       322 天前
    @lisongeee #5 python 有个类似的,pdm ,也支持整台电脑每个包只保留一份,然后通过软链接引用啥的。

    但不清楚能不能多版本共存。。
    lisongeee
        14
    lisongeee  
       322 天前
    @wxf666

    nodejs 的 node_modules 机制本来就是为了多版本共存而存在的,但是也因此被诟病占用过多空间

    pnpm 主要解决 node_modules 空间占用过多的问题
    iLucis
        15
    iLucis  
       322 天前
    conda 不行吗?
    huluhulu
        16
    huluhulu  
    OP
       322 天前
    @hsfzxjy 嗯,这个方法也不错。直接当两个独立的服务。
    xiaoqiao24
        17
    xiaoqiao24  
       318 天前
    docker A 安装低版本,然后使用 A 作为 baseimage ,再安装高版本,最后打出来的镜像两个版本都有。
    虽然在安装的时候会提示不兼容,但是并不影响安装。最后代码也能跑起来。
    huluhulu
        18
    huluhulu  
    OP
       318 天前
    @xiaoqiao24 这真的是我未曾想到的方法
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2062 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 453ms · UTC 00:17 · PVG 08:17 · LAX 17:17 · JFK 20:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.