特定于应用程序的PYTHONPATH

时间:2011-07-22 03:57:50

标签: python pythonpath sys.path

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

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

实施例

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

2 个答案:

答案 0 :(得分:1)

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

\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__定义为该目录中的模块列表,如果脚本尝试,则要导入该模块使用import *

答案 1 :(得分:0)

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