Python embedded 自动添加工作目录到搜索路径

发布时间 2023-08-27 00:03:55作者: 周上行Ryer

前言

本文提及的解决方案仅针对 Windows,毕竟 Linux 上应该没人会闲到专门去处理这种问题。

相较于安装版的 Python,便携版 Python 的模块并不会将工作目录或目标执行脚本添加到搜索路径中。

临时的解决方案为手动添加搜索路径,如下:

import sys
sys.path.append('.')

对于简单项目该方案或许够用,但是其侵入式的特征使得该方案并不像看上去的那样易用。

尤其是当这种需求出现在第三方库的安装中,该种情形下,就不得不手动拉取源码包并将安装脚本 setup.py 或相关文件中添加上述代码,令人不爽的程度大大增加。

解决方案

在 embedded 版本中,可以在 python???._pth 中添加默认搜索路径,添加的方式仅包含 Pathimport site 两种。

由于相对路径的添加时基于 python???._pth 所在目录进行指定的,故无法通过指定相对路径或绝对路径的方式使其自动添加实际的工作路径为模块搜索路径。

那么处理该问题的着手点就只能落在 import site 这一具有无限可能性选择上。

site 模块是 python 的内置模块,对于 embedded 版本,该模块位于 python???.zip 中,存在的形式为 pyc 预编译版本。

为了能够使 import site 执行想要的代码,那么无疑就需要替换自带的 site 模块。

在这里不妨在 python 根目录的 Lib 目录下创建 site.py 用于覆盖。

为了能够搜搜索到自定义的 site 模块,编辑 ._pth 文件如下:

python???.zip
Lib
Lib/site-packages

# Uncomment to run site.main() automatically
import site

只需确保包含 Libimport site 即可,其中的 python???.zip 请自行替换为对应版本的内置库文件,如 python311.zip

由于 python???.zip 总是在搜索顺序的最高优先级(可能与事实不符,但不影响接下来的操作),故而为了 import site 能够成功定位到自定义的 Lib/site.py,必须删除 python???.zip 中的 site.pyc 模块。

完成以上操作后,在 Lib/site.py 中写入以下内容即可完成工作目录的自动添加:

import sys
if __name__ == '__main__':
	sys.path.append('.')

为了确保 site 模块功能的一致性,相较于上面的简单替换,更推荐的处理方式是:拷贝对应版本官方的 site.py 并在最末添加 sys.path.append('.')

按照同样的操作可以处理其它类似的问题或在 site.py 中加上更多花活,但建议只在 site 模块完成搜索路径的预处理工作。