我有这样的文件夹结构,每次尝试使用相对导入时,都会引发错误
├── graphics
│ ├── __init__.py
│ ├── A
│ │ ├── __init__.py
│ │ ├── grok.py
│ │ └── spam.py
└── B
├── __init__.py
└── bar.py
spam.py/
def func():
pass
bar.py/
def f():
pass
所有这些代码都在grok.py中进行了测试:
from . import spam
# ImportError: cannot import name 'spam'
from .spam import func
# ModuleNotFoundError: No module named '__main__.spam'; '__main__'
is not a package
from ..B import bar
# ValueError: attempted relative import beyond top-level package
以下代码均不会导致任何错误:
from graphics.A import spam
from graphics.A.spam import func
from graphics.B import bar
from graphics.B.bar import f
答案 0 :(得分:2)
我假设当您说“ 在grok.py中测试过”时,您正在像这样运行它:
python3 graphics/A/grok.py
python3 A/grok.py
python3 grok.py
在Packages和Intra-Package References上的Python文档中,有一条注释说:
请注意,相对导入基于当前名称 模块。由于主模块的名称始终为“
__main__
”, 旨在用作Python应用程序主模块的模块 必须始终使用绝对导入。
当您运行grok.py
时,它将被视为主模块,并且只有在您使用绝对导入的情况下,导入才起作用(假设您未对sys.path
进行任何更改,我们将在后面介绍)。您可以通过将print(__name__)
放在grok.py的开头来进行测试,这将打印出“ __main__
”。
如果在调用main.py
模块的图形包下有单独的python文件(例如grok
),则相对导入实际上将正常工作:>
├── graphics
│ ├── __init__.py
| ├── main.py <<---- add this
│ ├── A
│ ├── B
在main.py
中,我们仅导入grok
模块:
from A import grok
在grok.py
中,我们测试相对导入:
from . import spam
spam.spam_func()
from .spam import spam_func
spam_func()
from B import bar
bar.bar_func()
在spam.py
中:
def spam_func():
print("spammy")
在bar.py
中:
def bar_func():
print("barry")
运行main.py
时:
graphics$ python3 main.py
spammy
spammy
barry
您不会收到任何先前的错误。相对进口工作。请注意,要从B
导入,我使用了from B
而不是from ..B
。这是因为导入路径是从main.py
的角度来看的。您可以通过在main.py
顶部添加以下内容来进行测试:
import sys
print(sys.path)
# prints a list, ['/path/to/graphics/',...]
如果您进行了from ..B
的操作,则意味着/path/to/graphics/../
当然没有B
模块(因此,您将获得“ 尝试的相对导入超出顶级”包”错误)
现在让我们说您不想使用单独的main.py
,而您想直接运行grok.py
。您可以做的是手动将graphics
软件包的路径添加到sys.path
。然后,您可以在from A
中进行from B
和grok.py
。
import sys
sys.path.append("/full/path/to/graphics/")
from A import spam
spam.spam_func()
from B import bar
bar.bar_func()
如果您想“入侵” sys.path
,建议您阅读sys.path
的更多内容,并查看其他讨论ways of adding paths to sys.path
的相关文章。