【问题标题】:Application-specific PYTHONPATH特定于应用程序的 PYTHONPATH
【发布时间】:2025-12-10 00:15:01
【问题描述】:

我有一个包含一系列包的应用程序。有相当多的模块引用了包层次结构中更高的其他模块。如下例所示,我可以使用相对导入来解决这个问题。但是,直接运行模块进行测试会失败,并出现 Attempted relative import in non-package 异常。

有没有更好的方法来组织我的应用程序或导入语句,以便模块可以单独执行以进行测试并从其他模块导入?

示例

\spam
    \morespam
        child.py
    base.py
\eggs
    user.py

base.py

class Base(object):
    def hello(self):
        print 'Um, wot?'

child.py

from ..base import Base       # references the parent package correctly, 
                              # but fails when this module is executed individually

class Child(Base):
    def hello(self):
        print 'Hello, world!'

if __name__ == '__main__':
    import unittest
    # ... unit test code ...

user.py

from spam.morespam.child import Child
print Child().hello()

现有解决方案

我发现我可以将以下标头添加到需要引用层次结构中更高模块的模块的顶部:

if __name__ == '__main__':
    import sys, os
    sys.path.append(os.path.abspath(os.path.join(sys.path[0], '..')))

缺点是我需要在所有地方添加此代码,而且它不是恒定的:'..' 相对路径根据层次结构中包的深度而变化。

其他可能的解决方案...

  1. 我可以使用我的应用程序根目录创建一个 .pth 文件。不幸的是,这必须添加到我的 Python 安装的 site-packages 文件夹中,因此它不是特定于应用程序的。
  2. 我可以temporarily add my application root to the PYTHONPATH,让我的所有模块都从根目录引用包。不过,这消除了通过简单地调用 python.exe whatever.py 来运行脚本的简单性。
  3. 我可以编写某种模块,当导入它时,它会在我的应用程序的根文件夹中查找标记文件。然后可以将这个通用模块安装到我的本地 Python 安装中,并由我的应用程序中的每个模块导入,从而保证根目录位于 PYTHONPATH 中,无论我正在执行哪个模块。

【问题讨论】:

    标签: python pythonpath sys.path


    【解决方案1】:

    您需要将__init__.py 添加为要从中导入的文件夹中的空文件。这样做会导致 python 将目录视为包,允许您在导入语句中使用它们:

    \spam
        \morespam
            __init__.py
            child.py
        __init__.py
        base.py
    \eggs
        __init__.py
        user.py
    

    一旦你这样做并建立你的 PYTHONPATH 到这个目录的基础,你就可以进行导入:

    base.py

    from morespam.child import Child
    from ..eggs import user
    

    虽然__init__.py 文件只需要存在,但您也可以在此文件中定义变量__ALL__ 作为该目录中您想要导入的模块列表,如果脚本尝试使用@987654326 @。

    【讨论】:

    • 我在示例代码中省略了 __init__.py 文件,因为它们与我的问题并不真正相关。我的包设置得很好,完全可以被外部模块使用。我的问题是我想知道如何在其中一个子包中运行脚本,以便它可以导入包层次结构中更高的模块,而无需将我的应用程序根添加到PYTHONPATH
    【解决方案2】:

    我使用 PyCharm 解决了这个问题,它每次运行我的应用程序时都会自动将我的源根目录添加到 PYTHONPATH。据我所知,PyCharm 基本上为我做了选项 #2。

    【讨论】:

      最近更新 更多