首页 > 解决方案 > 导入再次导入另一个模块的模块时出现 ModuleNotFoundError

问题描述

我的目录结构:

test/
    algo/
        base.py
        func.py
    main.py

func.py进口basemain.py进口func。脚本是:

# base.py

def base():
    pass
# func.py

from base import base
def func():
    base()

if __name__ == '__main__':
   func()
# main.py 

from algo.func import func 
if __name__ == '__main__':
   func()

当我执行时func.py,很好:

cd test/algo
python func.py # OK

但是main.py如果失败则运行时:

cd test
python main.py # => ModuleNotFoundError: No module named "base"

现在,如果我为in添加.前缀:basefunc.py

from .base import base # add dot prefix here
def func():
    base()

if __name__ == '__main__':
   func()

这次运行main.py正常,但是运行func.py报错: ModuleNotFoundError: No module named '__main__.base'; '__main__' is not a package

为什么这个 ?

什么是正确的导入方式basefunc以便func可以直接执行,并由 导入main

谢谢!

我的环境:MacOS,python3.7.4

标签: pythonpython-3.xpython-importimporterror

解决方案


看起来您将algo/其视为 Python 包,在这种情况下您可以使用:

# func.py
from algo.base import base

为什么它有效?这是因为 Python 解释器在其模块搜索路径 ( sys.path) 中添加了执行的文件目录。所以Python看到algo/它下面有一个目录,import algo交友工作。

现在,如果您想func.py直接运行,则会遇到问题:algo/无法再发现该目录,sys.path并且您遇到了导入错误,而您的代码是正确的。

完成这项工作的正确方法是告诉 Python 如何找到你的包。

快速而简单的方法是使用 PYTHONPATH 将包含您的包的目录添加到sys.path

PYTHONPATH=. python3 algo/func.py

干净的方法将在稍后出现:如果您正确打包项目(例如通过添加 apyproject.toml和 a setup.cfg,请参阅https://packaging.python.org/tutorials/packaging-projects/),那么您将能够安装你的包:

pip install .

“安装”的意思是“将包放在 Python 期望的地方”,所以很明显,一旦安装,一切import algo都会正常工作,无需修改 PYTHONPATH,并且不依赖于您当前的工作目录。

__init__.py最后一句话,你应该在你的文件夹中放置一个空文件algo/,使它成为一个合适的 Python 包,没有它,它是Python namespace package一个有点不同的东西,不是你真正想要的。

而且,你听说过__main__.py吗?它是您运行时执行的命名空间python3 -m YOUR_PACKAGEpython3 -m algo在您的示例中)。


推荐阅读