我试图遵循PEP 328,其目录结构如下:
pkg/
__init__.py
components/
core.py
__init__.py
tests/
core_test.py
__init__.py
在core_test.py中,我有以下import语句
from ..components.core import GameLoopEvents
然而,当我运行时,我得到以下错误:
tests$ python core_test.py
Traceback (most recent call last):
File "core_test.py", line 3, in <module>
from ..components.core import GameLoopEvents
ValueError: Attempted relative import in non-package
四处搜索,我发现“相对路径即使使用__init__.py也无法工作”和“从相对路径导入模块”,但它们都没有帮助。
这里有什么我遗漏的吗?
这种方法对我有效,比一些解决方案更不杂乱:
try:
from ..components.core import GameLoopEvents
except ValueError:
from components.core import GameLoopEvents
父目录位于我的PYTHONPATH中,父目录和此目录中有__init__.py文件。
上面的方法在python 2中总是有效的,但是python 3有时会遇到ImportError或ModuleNotFoundError(后者在python 3.6中是新的,也是ImportError的一个子类),所以下面的调整对我在python 2和3中都有效:
try:
from ..components.core import GameLoopEvents
except ( ValueError, ImportError):
from components.core import GameLoopEvents
这种方法对我有效,比一些解决方案更不杂乱:
try:
from ..components.core import GameLoopEvents
except ValueError:
from components.core import GameLoopEvents
父目录位于我的PYTHONPATH中,父目录和此目录中有__init__.py文件。
上面的方法在python 2中总是有效的,但是python 3有时会遇到ImportError或ModuleNotFoundError(后者在python 3.6中是新的,也是ImportError的一个子类),所以下面的调整对我在python 2和3中都有效:
try:
from ..components.core import GameLoopEvents
except ( ValueError, ImportError):
from components.core import GameLoopEvents
这取决于您希望如何启动脚本。
如果您想以经典的方式从命令行启动UnitTest,即:
python tests/core_test.py
然后,因为在这种情况下,“components”和“tests”是同级文件夹,所以可以使用sys.path模块的insert或append方法导入相关模块。类似于:
import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents
否则,您可以使用“-m”参数启动脚本(请注意,在本例中,我们讨论的是一个包,因此您不能使用“.py”扩展名),即:
python -m pkg.tests.core_test
在这种情况下,您可以简单地使用相对导入:
from ..components.core import GameLoopEvents
您最终可以将这两种方法混合使用,这样无论如何调用脚本,脚本都能正常工作。例如:
if __name__ == '__main__':
if __package__ is None:
import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents
else:
from ..components.core import GameLoopEvents