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
xgq89757
V2EX  ›  Python

关于 Python 环境可复现性请教

  •  
  •   xgq89757 · 14 小时 37 分钟前 · 1561 次点击
    公司 toB 项目 python 三方依赖有 150+,有没有比较优雅的方式能严格按照 requirements.txt (可能存在版本冲突)复现依赖环境,pip install -r requirements.txt 有个问题就是没准过段时间构建出来的环境就和 requirements.txt 中的不一致了

    目前的做法是将环境做成了基础镜像,每次交付都基于这个镜像打包。不同版本有增量依赖或版本调整时在 Dockerfile 中单独 pip install ,但这也存在基础镜像管理和基础镜像复现的问题。
    46 条回复    2025-08-15 20:12:30 +08:00
    dzdh
        1
    dzdh  
       14 小时 32 分钟前
    用 uv 。lock 版本。
    JoeJoeJoe
        2
    JoeJoeJoe  
    PRO
       14 小时 28 分钟前
    可以给项目加个虚拟环境, python 应该有很多这样的库, pyenv, venv 之类的.

    参考链接:
    1. https://www.cnblogs.com/doublexi/p/15783355.html
    2. https://www.cnblogs.com/doublexi/p/15786911.html
    blackshadow
        3
    blackshadow  
       14 小时 21 分钟前
    venv + requirement ,还有约定指定的 python 版本。 当然,即使这样,python 构建出的成果也有可能有问题。 我曾经在不同的电脑完全一模一样 venv ,依赖版本一样的环境,用 pyinstaller 打包的结果,不一样。😂
    xgq89757
        4
    xgq89757  
    OP
       14 小时 21 分钟前
    @JoeJoeJoe 虚拟环境是有的,目前用的 miniforge ,主要是环境复现的问题,最近在尝试 pixi
    iorilu
        5
    iorilu  
       14 小时 20 分钟前
    复杂的项目直接打包部署镜像是最好的
    JoeJoeJoe
        6
    JoeJoeJoe  
    PRO
       14 小时 18 分钟前
    @xgq89757 环境复现是个啥场景啊, requirements.txt 指定版本号的话, install 下来的每次不应该都是相同的吗😂 没太理解
    Cooky
        7
    Cooky  
       14 小时 15 分钟前
    @JoeJoeJoe 除了 pip 包剩下的应该就是依赖的二进制库了,二进制库都要一直那就得上 docker 了
    xgq89757
        8
    xgq89757  
    OP
       14 小时 15 分钟前
    @dzdh 用 ai 对比了 uv 和 pixi ,ai 指出 uv 对需要二进制编译的包支持不太友好,项目中算法和机器学习库不少,最近在尝试 pixi ,仍遇到安装环境出现版本冲突的问题,可能 toml 没有编排好的问题。后边准备尝试下 uv ,验证下 ai 的结论。
    xgq89757
        9
    xgq89757  
    OP
       14 小时 13 分钟前
    @JoeJoeJoe 没准过几个月 pip install -r 下来发现有些包就不一样了😂
    xgq89757
        10
    xgq89757  
    OP
       14 小时 11 分钟前
    @blackshadow 还有就是项目是在某些版本冲突下稳定运行的,-r 构建就会报错退出,只能先注释掉冲突的包,最后在单独 install
    JoeJoeJoe
        11
    JoeJoeJoe  
    PRO
       14 小时 11 分钟前
    @xgq89757 #9 还有这种情况呢? 我倒是一直没注意过, 我一直是能跑就行.

    ps: 要是怕这个的话, 直接把三方依赖的包放到共享文件夹吧, 指定一下 python 包路径
    xgq89757
        12
    xgq89757  
    OP
       14 小时 10 分钟前
    @JoeJoeJoe 所以暂时的方法是打成了基础镜像。
    killva4624
        13
    killva4624  
       14 小时 9 分钟前
    @xgq89757 #9 pip install -r 为啥不会一样,没指定版本号吗?
    maocat
        14
    maocat  
       14 小时 3 分钟前 via Android
    合理怀疑 requirements.txt 里面没有吧对应的的包的关联依赖包拉进来, 试一试 pip freeze 全量输出
    xgq89757
        15
    xgq89757  
    OP
       14 小时 1 分钟前
    @killva4624 全指定了版本号的,清单是从当前稳定运行的环境中 pip list --format=freeze 拉下来的,
    后续就是想通过这个清单复现环境,但是有些包会出现版本冲突或者构建下来的环境和清单不一致。
    xgq89757
        16
    xgq89757  
    OP
       13 小时 55 分钟前
    @iorilu 目前就是这样的,运行环境打包成基础镜像,交付打包时再将混淆的工程打包进镜像。但是遇到不允许容器化部署的客户就比较麻烦了,要根据客户的环境做离线包,客户是金融、银行之类的基本都没有公网。
    blackshadow
        17
    blackshadow  
       13 小时 45 分钟前
    @xgq89757 感觉最好的办法就是你上面的了,一是容器化部署;二是全部的依赖包都本地保存离线版,环境里全部离线安装。 感觉你这个要求和我们之前很像,我们之前给客户装环境完全内网,rpm 服务都是自己搭建,找个大硬盘里面装了所有需要的离线包。
    Mithril
        18
    Mithril  
       13 小时 36 分钟前   ❤️ 2
    虽说也推荐你用 uv ,但你这个环境和要求,光靠 uv 是没法彻底解决的。你要考虑的是依赖的可信与供应链管理,而不简单的一个 lock 。

    正常做法是,内网搭建 pip 的镜像服务,并且配置多个 pip 仓库。至少三个,dev ,integration ,release 。只有 dev 是联通外网的 mirror ,其他两个是本地库。

    然后你开发的时候 pip 指向 dev 库,发版的时候,QA 和测试用 integration 库。这时候把你需要的指定版本的所有依赖从 dev 提升复制到 integration 库内。

    当 QA 和测试完成,再次把这些依赖到 release 库内。作为最终 release 的二进制依赖,同时对依赖进行漏洞检查和制做 SBOM 。

    当然你可以根据你们的要求自己调整一下,可能也用不到这么严格的流程。但本质上为了避免 FOSS 的供应链风险,你应该自己保留所有依赖的二进制及其代码以供审查,并且可以完全从本地构建你的产品。

    别忘了之前 npm 下毒的事。
    xgq89757
        19
    xgq89757  
    OP
       13 小时 31 分钟前
    @JoeJoeJoe 默认行为:pip 会安装满足条件的最新版本,比如某个三方依赖的子依赖要求是> 1.0 ,这个子依赖当时的最新版本是 1.5 ,当时安装的会是 1.5 ,过一段时间这个子依赖的版本迭代到到了 1.7 ,在这时它会安装 1.7 ,这个好解决,在 requirements.txt 中强制子依赖==1.5 ,但因为项目迭代比较久了,后续有人增加或修改了某些依赖,这个操作是直接在环境中单独安装的(这时候不会暴露冲突问题),然后归档依赖版本到 requirements.txt ,但是项目就是在这样的冲突下稳定运行的,时间久了你想在其他服务器复现环境再通过 requirements.txt 构建的时候就会发现有的包有版本冲突,这时候冲突的依赖只能单独安装,然后刷一遍版本。
    momocraft
        20
    momocraft  
       13 小时 30 分钟前
    pip freeze 却不能重现有点怪

    涉及到全局安装的包,或者嵌套的 venv 吗?
    zhoudaiyu
        21
    zhoudaiyu  
    PRO
       12 小时 55 分钟前
    直接 docker 不就完事了
    jasonchen168
        22
    jasonchen168  
       11 小时 58 分钟前
    我也遇到了,头大。而且 Mac 和 Windows 还有些库不一样
    clemente
        23
    clemente  
       11 小时 55 分钟前
    pip install -r requirements.txt --target /home/local_env


    下载好 然后上报保存

    下次指定 pythonpath 到这个目录就好
    clemente
        24
    clemente  
       11 小时 54 分钟前
    @momocraft

    1. 有些包 是 现场编译的 没有预编译 的情况
    2. 有些包 指定的依赖 他没有指定版本. 时间久了就会出依赖冲突
    irory
        25
    irory  
       11 小时 48 分钟前
    pip 安装可以离线包的,所有依赖都下载本地目录。
    tomczhen
        26
    tomczhen  
       11 小时 45 分钟前
    不涉及编译安装的话还是好解决的,如果想规避这个问题,以我目前的看法是只能选择提供编译好的二进制仓库源才行,这样就只剩下 conda 可以选了。考虑到商用的话,这个问题确实没那么容易。
    xgq89757
        27
    xgq89757  
    OP
       11 小时 45 分钟前
    @Mithril 我们确实没这么严格的流程,但是很赞,mark 。
    moudy
        28
    moudy  
       11 小时 35 分钟前 via iPhone
    @blackshadow 如果出现要打安全性补丁就完蛋了
    sazima
        29
    sazima  
       11 小时 34 分钟前
    使用 pip download 把包下载下来
    xgq89757
        30
    xgq89757  
    OP
       11 小时 32 分钟前
    还有种方式就是用脚本去逐个安装 requirements.txt 中的库了,绕过-r 的冲突检查。冲突的库单独装只会有 warnning ,但不会终止安装,最后再扫一遍版本。
    BingoW
        31
    BingoW  
       11 小时 29 分钟前
    我记得 pip 是有一个原生的方法的,直接将你本地环境所有依赖达成一个大的 zip 包,然后在目标服务器直接安装就好了,目标服务器不需要联网,所有版本都跟本地服务器一致。
    xgq89757
        32
    xgq89757  
    OP
       11 小时 22 分钟前
    @BingoW 之前公司内网的开发、测试、试用环境就是类似方法,直接压缩 miniforge 的 env 下对应工程的虚拟环境进行迁移。后来让我全部改成容器化部署了,省去了很多工作量。测试基于镜像测试,交付时直接交付镜像文件。
    xgq89757
        33
    xgq89757  
    OP
       11 小时 21 分钟前
    @moudy 目前是基于基础镜像在工程的 Dockerfile 中打补丁。
    BingoW
        34
    BingoW  
       9 小时 51 分钟前
    @xgq89757 嗯 这个是很好的办法
    SunDoge
        35
    SunDoge  
       9 小时 22 分钟前
    @xgq89757 #8 大部分算法库都提供了预编译二进制包,用 uv 很少会出现不友好的地方。pypi 的 python 库比 conda 、conda-forge 还是多的,用 pixi 会遇到部分依赖在 pypi ,部分依赖在 conda 的问题,解决依赖冲突会比较麻烦。
    misoomang
        36
    misoomang  
       9 小时 15 分钟前
    即使 requirment.txt 的包指定了版本,每个包对应支持的 Python 版本的范围会不一样,如果传统部署的 Python 版本不固定,即使指定了 pip 包的版本,在不同的 Python 版本下安装也会出现差异
    Hopetree
        37
    Hopetree  
       9 小时 13 分钟前
    如果是容器肯定是搞成基础镜像是最优解啊,特别是机器学习应该会设计到一些需要编译使用的第三方库,这种库的安装不仅仅是 pip 能解决的,还跟服务器环境有关,很难保证依赖顺利安装,所以基础镜像就可以忽略这些问题
    h404bi
        38
    h404bi  
       9 小时 10 分钟前
    我看你说在用 pixi 了,那有试过用 pixi-pack 直接打包环境么?

    https://github.com/Quantco/pixi-pack
    SmiteChow
        39
    SmiteChow  
       9 小时 8 分钟前
    十年前的工程实践是把所有包下载下来放到 git 里面去,现在依然是这样,没办法。
    lovepocky
        40
    lovepocky  
       8 小时 57 分钟前
    poetry
    1018ji
        41
    1018ji  
       8 小时 6 分钟前
    把所有的库都捞下来,库还依赖库,只搞几个必然起飞
    xgq89757
        42
    xgq89757  
    OP
       6 小时 49 分钟前
    @Hopetree 是的,我们的项目就是模型平台,会有数据分析和建模场景,不少库需要编译。客户环境也不统一,有 arm 的有 x86 的,还有的会有信创要求。
    xgq89757
        43
    xgq89757  
    OP
       6 小时 46 分钟前
    @SunDoge 目前就有 conda 、pypi 混用的情况,有些库 pypi 装起来不是缺这个就是缺那个,然后就直接用 conda 装了。
    xgq89757
        44
    xgq89757  
    OP
       6 小时 44 分钟前
    @SmiteChow 考虑跨平台还是不太合适,现在的一个交付镜像就得两个过 g 大小。
    xgq89757
        45
    xgq89757  
    OP
       6 小时 42 分钟前
    @h404bi 打包和环境迁移到不是问题,主要是想寻求种环境从 0 复现的优雅方式。
    fightff
        46
    fightff  
       5 小时 34 分钟前
    以前我们 python 项目的管理是集中维护 requirement txt, 所有人开发都用统一指定的固定版本。依赖需要升级或者切版本的话要 review 之后再修改。可以减少一定的环境问题。
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1202 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 17:46 · PVG 01:46 · LAX 10:46 · JFK 13:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.