Python 以嵌套结构导入

Python imports in nested structure

有如下结构:

project/
   I-----main.py
   I-----src/
          I----__init__.py (empty)
          I----util.py
          I----shared/
                  I----__init__.py (empty)
                  I----hello.py 


#main.py
from src import util

#util.py (runs without errors)
from shared import hello

#hello.py (runs without errors)
def hello():
    print("Hello")

我尝试运行main.py,得到结果

ModuleNotFoundError: No module named 'shared'

如何在 main.py 中修复导入?

你可能想要 from src.shared import hello

您需要使用相对导入:

from .shared import hello

如果您 运行 util.py 正常,.../project/src 附加到 sys.path 并且 Python 可以找到导入。但是,当你 运行 main.py 时, .../project/ 附加到 sys.path,并且 Python 找不到 shared 模块。通过使用相对导入,Python 查找相对于当前包的模块名称,可以找到 shared 模块。

另请参阅:Relative imports for the billionth time

造成此类故障的主要原因有两个:

  1. 模块导入: 您没有正确导入模块。您可以通过提及其子模块的导入使用模块的 __init__.py 导入它,也可以通过导入直接放置完整路径。例如,您可以使用 from src.shared import hello。或者,在 __init__.py 文件中的 src 模块中,您可以添加 from shared import hello。这也将起作用,因为每当您导入模块时,该模块中第一个 运行 就是该文件的 __init__.py

  2. Circular imports: 这不是你的情况,但我提出这个问题是因为很多时候我们忽略了这一点并陷入困境。当两个模块相互依赖时,就会发生循环导入。我已经在 post、What is Circular Import and how to avoid it.

    中描述了它发生的原因以及如何避免它

我找到了可能的解决方案(效果很好):


    #util.py
    import sys
    from pathlib import Path
    
    root = Path(__file__).parent.parent #depends on file's place in general structure
    sys.path.append(str(root))
    import src.shared.hello as hello