sky*_*der 713 python init package python-import importerror
我正在尝试遵循PEP 328,具有以下目录结构:
pkg/
__init__.py
components/
core.py
__init__.py
tests/
core_test.py
__init__.py
Run Code Online (Sandbox Code Playgroud)
在core_test.py我有以下import语句
from ..components.core import GameLoopEvents
Run Code Online (Sandbox Code Playgroud)
但是,当我运行时,我收到以下错误:
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
Run Code Online (Sandbox Code Playgroud)
搜索周围我发现" 相对路径甚至不能使用__init__.py "和" 从相对路径导入模块 ",但它们没有帮助.
这里有什么我想念的吗?
Bre*_*arn 612
详细阐述Ignacio Vazquez-Abrams的答案:
Python导入机制相对于__name__当前文件的工作方式.直接执行文件时,它没有通常的名称,而是具有"__main__"其名称.所以相对进口不起作用.
正如Igancio建议的那样,您可以使用该-m选项执行它.如果您的程序包的一部分要作为脚本运行,您还可以使用该__package__属性来告诉该文件它应该在程序包层次结构中具有什么名称.
有关详细信息,请访问http://www.python.org/dev/peps/pep-0366/.
Ign*_*ams 426
是.你没有把它作为一个包使用.
python -m pkg.tests.core_test
Run Code Online (Sandbox Code Playgroud)
ihm*_*ihm 198
import components.core如果将当前目录附加到sys.path以下目的,则可以直接使用:
if __name__ == '__main__' and __package__ is None:
from os import sys, path
sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
Run Code Online (Sandbox Code Playgroud)
Pao*_*lli 178
这取决于您希望如何启动脚本.
如果要以经典方式从命令行启动UnitTest,即:
python tests/core_test.py
Run Code Online (Sandbox Code Playgroud)
然后,因为在这种情况下'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
Run Code Online (Sandbox Code Playgroud)
否则,您可以使用'-m'参数启动脚本(请注意,在这种情况下,我们正在讨论一个包,因此您不能提供'.py'扩展名),即:
python -m pkg.tests.core_test
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您可以像以前一样使用相对导入:
from ..components.core import GameLoopEvents
Run Code Online (Sandbox Code Playgroud)
您最终可以混合使用这两种方法,这样无论调用方式如何,您的脚本都可以正常工作.例如:
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
Run Code Online (Sandbox Code Playgroud)
All*_*gwa 20
在core_test.py中,执行以下操作:
import sys
sys.path.append('../components')
from core import GameLoopEvents
Run Code Online (Sandbox Code Playgroud)
Moh*_*med 10
问题在于您的测试方法,
你试过了 python core_test.py
那么你会得到这个错误 ValueError: Attempted relative import in non-package
原因:您正在从非包装源测试您的包装。
所以从包源测试你的模块。
如果这是您的项目结构,
pkg/
__init__.py
components/
core.py
__init__.py
tests/
core_test.py
__init__.py
Run Code Online (Sandbox Code Playgroud)
光盘包
python -m tests.core_test # dont use .py
Run Code Online (Sandbox Code Playgroud)
或来自外部 pkg/
python -m pkg.tests.core_test
Run Code Online (Sandbox Code Playgroud)
.如果要从同一目录中的文件夹导入,则单个。每后退一步,再加一个。
hi/
hello.py
how.py
Run Code Online (Sandbox Code Playgroud)
在 how.py
from .hi import hello
Run Code Online (Sandbox Code Playgroud)
如果你想从 hello.py 导入 how
from .. import how
Run Code Online (Sandbox Code Playgroud)
如果您的用例是用于运行测试,并且它是接缝,那么您可以执行以下操作.而不是像python core_test.py使用测试框架那样运行测试脚本pytest.然后在命令行上输入
$$ py.test
Run Code Online (Sandbox Code Playgroud)
这将在您的目录中运行测试.这得到周围人的问题__name__的存在__main__,是由@BrenBarn指出.接下来,将一个空__init__.py文件放入您的测试目录中,这将使测试目录成为您的包的一部分.然后你就可以做到
from ..components.core import GameLoopEvents
Run Code Online (Sandbox Code Playgroud)
但是,如果您将测试脚本作为主程序运行,那么事情将再次失败.所以只需使用测试运行器.也许这也适用于其他测试跑步者,nosetests但我还没有检查过.希望这可以帮助.
我的快速修复是将目录添加到路径:
import sys
sys.path.insert(0, '../components/')
Run Code Online (Sandbox Code Playgroud)
由于您已经将所有内容标记为模块,因此如果您将其作为 Python 模块启动,则无需使用相对引用。
代替
from ..components.core import GameLoopEvents
Run Code Online (Sandbox Code Playgroud)
简单地
from pkg.components.core import GameLoopEvents
Run Code Online (Sandbox Code Playgroud)
当您从包的父包运行时,请使用以下命令:
python -m pkg.tests.core_test
Run Code Online (Sandbox Code Playgroud)