【问题标题】:How to maintain python application with dependencies, including my own custom libs?如何使用依赖项维护 python 应用程序,包括我自己的自定义库?
【发布时间】:2017-07-26 14:18:18
【问题描述】:

我正在使用 Python 开发一些特定于公司的应用程序。有一个自定义共享模块(“库”)描述了一些数据和算法,并且有几十个 Python 脚本可以使用这个库。这些文件很多,所以它们被组织在子文件夹中

myproject
    apps
        main_apps
            app1.py
            app2.py
            ...
        utils
            util1.py
            util2.py
            ...
    library
        __init__.py
        submodule1
            __init__.py
            file1.py
            ...
        submodule2
            ...

用户想要运行这些脚本,只需转到 myproject\utils 并启动“py util2.py some_params”即可。这些用户中有许多是开发人员,因此他们经常想要编辑库并立即使用更新的代码重新运行脚本。该项目还使用了一些 3rd 方库,我想确保每个人都使用这些库的相同版本。

现在,我遇到了两个关键问题:

  1. 如何从(应用)引用(库)?
  2. 如何管理第 3 方依赖项?

第一个问题对于很多 Python 开发者来说都很熟悉,并且在 SO 上被问过很多次:指示 Python 从 "....\library" 导入包是相当困难的。我测试了几种不同的方法,但似乎 python 不愿意在任何地方搜索包,而是在标准库位置或脚本本身的文件夹中。

  • 相对导入不起作用,因为脚本不是库的一部分(即使它是,当脚本直接执行时这仍然不起作用,除非它放在我想要的“根”项目文件夹中喜欢避免)
  • 将 .pth 文件(从阅读 this document 可能会想到)到脚本文件夹显然没有任何效果

当然直接干预 sys.path 的工作,但是像这样的样板代码在每个脚本文件中看起来都很糟糕

import sys, os.path
here = os.path.dirname(os.path.realpath(__file__))
module_root = os.path.abspath(os.path.join(here, '../..'))
sys.path.append(python_root)
import my_library

我意识到发生这种情况是因为 Python 希望正确“安装”我的库,如果这个库与使用它的脚本分开开发,那确实是唯一正确的方法。但不幸的是,情况并非如此,我认为每次更改库时都重新“安装”库将非常不方便并且容易出错。

第二个问题很简单。有人在我们的 app/lib 中添加了一个新的 3rd 方模块,其他人在更新他们的应用程序后开始看到导入问题。几个开发分支,用户执行 pip 安装的不同时刻,很少回滚 - 每个人最终都会使用不同版本的 3rd 方模块。就我而言,由于许多开发人员大量使用较旧的 Python 2.x 代码,而我想继续使用 Python 3.x,因此事情变得更加复杂

在为我的问题寻找可能的解决方案时,我发现 Python 中有一个非常出色的虚拟环境功能。事情看起来很光明:

  1. 为我的项目创建一个 venv
  2. 将 Requirements.txt 文件作为应用程序的一部分分发,并提供一个相应地填充 venv 的脚本
  3. 将我自己的库符号链接到 venv site_packages 文件夹,以便 Python 始终检测到它

这个解决方案看起来非常自然和强大。我明确地为我的项目设置了我自己的环境,并将我需要的任何东西放入这个 venv,包括我自己的库,我仍然可以在运行中进行编辑。它确实有效。但是调用 activate.bat 来激活这个 python 环境和另一个批处理文件来停用它是一团糟,尤其是在 Windows 平台上。正在编辑 sys.path 的样板代码看起来很糟糕,但至少它不会像这个潜在的修复那样干扰用户体验。

所以我想问一个问题。

  1. 有没有办法将特定的 python venv 绑定到特定的文件夹,这样 python 启动器会自动将此 venv 用于这些文件夹中的脚本?
  2. 是否有更好的替代方法来处理我错过的这种情况?

我的项目环境是在 Windows 10 上运行的 Python 3.6。

【问题讨论】:

  • 您是否使用setuptools.py 来“安装”?如果是这样,您可以使用develop 命令行参数代替install,请参阅讨论here。这使您可以在库上工作并立即查看所做的更改。
  • 不幸的是,据我所知,对您有帮助的工具在 Windows 上并不真正可用。例如,您可以尝试寻找 autoenv 的等价物
  • 谢谢!这是一个很好的选择,我完全错过了。现在在我的项目中没有“安装”过程,脚本只是通过修改后的 sys.path 查找模块。我更喜欢使用 PIP 而不是 setuptools.py,但它有一个类似的选项 (pip install -e),这是使用我的自定义库与符号链接选项来初始化环境(虚拟或非虚拟)的更好方法。这样,在许多情况下,完全没有任何虚拟环境也可能是可以的(尽管我更喜欢保留一个以便更容易控制依赖关系)
  • 不幸的是,Windows 平台上的develop 选项似乎破坏了某些东西。安装程序显然是成功的,一个“library.egg-link”文件出现在 venv 的站点包中,但 Python 无法解决它(参见类似问题 stackoverflow.com/questions/10569846/…)。另一方面,在同一位置手动创建符号链接就可以了。
  • 那很不幸。就像我说的那样,我的印象是,很多工具并不是以 Windows 为重点开发的,而是事后才想到的。

标签: python windows python-3.x packaging python-venv


【解决方案1】:

我想我终于找到了一个合理的答案。只需在 venv 中添加指向 python 解释器的 shebang 行就足够了,例如

#!../../venv/Scripts/python

完整的项目结构如下所示

myproject
    apps
        main_apps
            app1.py (with shebang)
            app2.py (with shebang)
            ...
        utils
            util1.py (with shebang)
            util2.py (with shebang)
            ...
    library
        __init__.py
        submodule1
            __init__.py
            file1.py
            ...
        submodule2
            ...
    venv
        (python interpreter, 3rd party modules)
        (symlink to library)
    requirements.txt
    init_environment.bat

事情是这样的:

  1. venv 是一个虚拟 Python 环境,包含项目所需的一切
  2. init_environment.bat 是根据 requirements.txt 填充 venv 并将我的库的符号链接放入 venv 站点模块的脚本
  3. 所有脚本都以指向 venv 解释器的 shebang 行开头(带有相对路径)

有一个完整的自定义环境,其中包含我自己的所有库和使用它的脚本都将具有非常自然的导入。每当我的项目中的任何面向用户的脚本从控制台或 Windows 资源管理器启动时,Python 启动器还将自动选择 Python 3.6 作为解释器并加载相关模块。

缺点:

  1. 如果从其他文件夹调用脚本,则相对 shebang 将不起作用
  2. 用户仍需手动运行 init_environment.bat 以根据 requirements.txt 更新虚拟环境
  3. Windows 上的 init_environment 脚本需要提升权限才能进行符号链接(但希望 MS 奇怪的决定将在 2017 年 4 月即将推出的 Win10 更新中得到修复)

但是我可以忍受这些限制。希望这会帮助其他寻找类似问题的人。

还是很高兴听到其他选项(作为答案)和批评者(作为 cmets)。

【讨论】:

    猜你喜欢
    • 2019-11-19
    • 2019-11-02
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 2013-03-07
    • 2017-08-20
    • 1970-01-01
    • 2022-01-20
    相关资源
    最近更新 更多