PYTHONPATH 与 sys.path
- 2025-03-11 08:50:00
- admin 原创
- 62
问题描述:
我和另一位开发人员对是否应该使用PYTHONPATH
或sys.path
来允许 Python 在用户(例如,开发)目录中找到 Python 包存在分歧。
我们有一个具有典型目录结构的 Python 项目:
Project
setup.py
package
__init__.py
lib.py
script.py
在 script.py 中,我们需要执行import package.lib
。当包安装在 site-packages 中时,script.py 可以找到package.lib
。
但是,当从用户目录工作时,还需要做其他事情。我的解决方案是将 my 设置PYTHONPATH
为 include "~/Project"
。另一位开发人员想将这行代码放在 script.py 的开头:
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
这样 Python 就能找到 的本地副本package.lib
。
我认为这是一个坏主意,因为这条线只对开发人员或从本地副本运行的人有用,但我无法给出一个很好的理由来说明为什么这是一个坏主意。
我们应该使用PYTOHNPATH
、sys.path
还是两者都可以?
解决方案 1:
如果修改路径的唯一原因是为了让开发人员从他们的工作树中工作,那么您应该使用安装工具为您设置环境。virtualenv 非常流行,如果您使用 setuptools,您只需运行即可setup.py develop
在当前的 Python 安装中半安装工作树。
解决方案 2:
我讨厌 PYTHONPATH。我发现按用户设置(尤其是守护进程用户)并跟踪项目文件夹的移动非常麻烦。我更愿意sys.path
在独立项目的调用脚本中设置。
但这sys.path.append
不是解决问题的方法。您很容易得到重复项,而且它不会对.pth
文件进行排序。更好的(更易读的)site.addsitedir
:。
而且script.py
通常这不是执行此操作的更合适位置,因为它位于您想要在路径上提供的包内sys.path
。库模块当然不应该接触自身。相反,您通常会在包外有一个 hashbanged 脚本,用于实例化和运行应用程序,并且在这个简单的包装器脚本中,您可以放置部署详细信息,例如sys.path
-frobbing。
解决方案 3:
总体而言,我认为设置环境变量(如 PYTHONPATH)是一种不好的做法。虽然这对于一次性调试来说可能没问题,但将其作为
常规做法可能不是一个好主意。
使用环境变量会导致出现“它对我有用”的情况,因为其他人
报告代码库中存在问题。此外,人们可能对测试环境也采取同样的做法,导致测试对特定开发人员运行良好,但当其他人启动测试时可能会失败的情况。
解决方案 4:
除了前面提到的许多其他原因之外,你还可以指出硬编码
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
很脆弱,因为它假定了 script.py 的位置——只有当 script.py 位于 Project/package 中时,它才会起作用。如果用户决定将 script.py 移动/复制/符号链接到(几乎)其他任何地方,它就会中断。
解决方案 5:
由于前面提到的原因,无论是黑客攻击PYTHONPATH
还是直接使用都不是一个好主意。而对于将当前项目链接到 site-packages 文件夹,实际上有一种比 更好的方法,如下所述:sys.path
`python setup.py develop`
pip install --editable path/to/project
如果你的项目根文件夹中还没有 setup.py,那么这个就足以让你开始:
from setuptools import setup
setup('project')
解决方案 6:
我认为,在这种情况下使用 PYTHONPATH 是更好的选择,主要是因为它不会引入(可疑的)不必要的代码。
毕竟,如果你想到这一点,你的用户就不需要那个sys.path
东西,因为你的包将被安装到站点包中,因为你将使用一个包装系统。
如果用户选择从您所说的“本地副本”运行,那么我观察到,通常的做法是说明,如果在站点包之外使用,则需要将包手动添加到 PYTHONPATH。