如何修复这些相对导入错误
How can I fix these relative import error
我有这样的文件夹结构,每次尝试使用相对导入时,都会出现错误
├── 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
None 以下代码会导致任何错误:
from graphics.A import spam
from graphics.A.spam import func
from graphics.B import bar
from graphics.B.bar import f
我假设当你说“在 grok.py 中测试”时,你正在 运行 像这样:
python3 graphics/A/grok.py
python3 A/grok.py
python3 grok.py
在 Packages and Intra-Package References 的 Python 文档中,有一条注释说:
Note that relative imports are based on the name of the current
module. Since the name of the main module is always "__main__
",
modules intended for use as the main module of a Python application
must always use absolute imports.
当您 运行 grok.py
时,它被视为主模块,导入仅在您使用绝对导入时才有效(假设您未对 sys.path
进行任何更改,我们稍后再讲)。您可以通过将 print(__name__)
放在 grok.py 的开头来测试它,这将打印出“__main__
”。
如果您在调用您的图形包下有一个单独的 python 文件(例如 main.py
),那么您的相对导入 实际上 会起作用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
模块(因此,你会得到“attempted relative import超出 top-level 包 " 错误)
现在假设您不想使用单独的 main.py
,而是想直接 运行 grok.py
。您可以做的是手动将 graphics
包的路径添加到 sys.path
。然后你可以在 grok.py
.
中做 from A
和 from B
import sys
sys.path.append("/full/path/to/graphics/")
from A import spam
spam.spam_func()
from B import bar
bar.bar_func()
如果您想了解 "hacking" 和 sys.path
,我建议您多阅读 sys.path
and checking other related posts that discuss ways of adding paths to sys.path
。
我有这样的文件夹结构,每次尝试使用相对导入时,都会出现错误
├── 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
None 以下代码会导致任何错误:
from graphics.A import spam
from graphics.A.spam import func
from graphics.B import bar
from graphics.B.bar import f
我假设当你说“在 grok.py 中测试”时,你正在 运行 像这样:
python3 graphics/A/grok.py
python3 A/grok.py
python3 grok.py
在 Packages and Intra-Package References 的 Python 文档中,有一条注释说:
Note that relative imports are based on the name of the current module. Since the name of the main module is always "
__main__
", modules intended for use as the main module of a Python application must always use absolute imports.
当您 运行 grok.py
时,它被视为主模块,导入仅在您使用绝对导入时才有效(假设您未对 sys.path
进行任何更改,我们稍后再讲)。您可以通过将 print(__name__)
放在 grok.py 的开头来测试它,这将打印出“__main__
”。
如果您在调用您的图形包下有一个单独的 python 文件(例如 main.py
),那么您的相对导入 实际上 会起作用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
模块(因此,你会得到“attempted relative import超出 top-level 包 " 错误)
现在假设您不想使用单独的 main.py
,而是想直接 运行 grok.py
。您可以做的是手动将 graphics
包的路径添加到 sys.path
。然后你可以在 grok.py
.
from A
和 from B
import sys
sys.path.append("/full/path/to/graphics/")
from A import spam
spam.spam_func()
from B import bar
bar.bar_func()
如果您想了解 "hacking" 和 sys.path
,我建议您多阅读 sys.path
and checking other related posts that discuss ways of adding paths to sys.path
。