我有一个包含层次结构的应用程序。有许多模块可以引用包层次结构中更高层的其他模块。如下所示,我可以使用相对导入来解决这个问题。但是,直接运行模块进行测试会因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], '..')))
缺点是我需要在整个地方添加此代码,并且它不是常量:'..'
相对路径根据层次结构中包的深度而变化。
python.exe whatever.py
来消除运行脚本的简单性。答案 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。