我正在使用 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 方库,我想确保每个人都使用这些库的相同版本。
现在,我遇到了两个关键问题:
- 如何从(应用程序)引用(库)?
- 如何管理第三方依赖?
第一个问题对于很多 Python 开发者来说都很熟悉,并且在 SO 上被问过很多次:指示 Python 从 "....\library" 导入包是相当困难的。我测试了几种不同的方法,但似乎 python 不愿意在任何地方搜索包,而是在标准库位置或脚本本身的文件夹中搜索。
- 相对导入不起作用,因为脚本不是库的一部分(即使它是,当脚本直接执行时这仍然不起作用,除非它放在我想避免的“根”项目文件夹中)
- 将 .pth 文件(从阅读本文档中可能会想到)到脚本文件夹显然没有任何效果
当然直接干预 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 中有一个非常出色的虚拟环境功能。事情看起来很光明:
- 为 myproject 创建一个 venv
- 分发 Requirements.txt 文件作为应用程序的一部分,并提供一个相应地填充 venv 的脚本
- 将我自己的库符号链接到 venv site_packages 文件夹,以便 Python 始终检测到它
这个解决方案看起来非常自然和强大。我明确地为我的项目设置了我自己的环境,并将我需要的任何东西放入这个 venv,包括我自己的库,我仍然可以在运行中进行编辑。它确实有效。但是调用activate.bat来激活这个 python 环境和另一个批处理文件来停用它是一团糟,尤其是在 Windows 平台上。正在编辑 sys.path 的样板代码看起来很糟糕,但至少它不会像这个潜在的修复那样干扰用户体验。
所以有一个问题我想问。
- 有没有办法将特定的 python venv 绑定到特定的文件夹,所以 python 启动器会自动将此 venv 用于这些文件夹中的脚本?
- 有没有更好的替代方法来处理我错过的这种情况?
我的项目环境是在 Windows 10 上运行的 Python 3.6。