【问题标题】:How can I fix these relative import error如何修复这些相对导入错误
【发布时间】:2019-10-20 12:14:48
【问题描述】:

我有一个这样的文件夹结构,每次我尝试使用相对导入时,都会引发错误

├── 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

【问题讨论】:

    标签: python python-3.6 python-import


    【解决方案1】:

    我假设当您说“tested in grok.py”时,您正在像这样运行它:

    python3 graphics/A/grok.py
    python3 A/grok.py
    python3 grok.py
    

    PackagesIntra-Package References 上的Python 文档中,有一条注释说:

    请注意,相对导入是基于当前的名称 模块。由于主模块的名称总是“__main__”, 用作 Python 应用程序主模块的模块 必须始终使用绝对导入

    当您运行grok.py 时,它会被视为主模块,并且导入仅在您使用绝对导入时才有效(假设您未对sys.path 进行任何更改,我们稍后会介绍)。您可以通过将print(__name__) 放在 grok.py 的开头进行测试,这将打印出“__main__”。

    如果您在调用grok 模块的图形包下有一个单独的python 文件(例如main.py),那么您的相对导入实际上会起作用:

    ├── 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。然后你可以在grok.py中做from Afrom B

    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 的相关帖子。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-23
      • 1970-01-01
      • 2018-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多