如果我有
a.py
b.py
在b.py
中,我可以import a
但如果我有
c.py
m
a.py
b.py
在c.py
中做import m.b
,突然在b.py
中得到ModuleNotFoundError: No module named 'a'
怎么了?我看不出第二种情况与第一种有什么不同
所以。。。在最初启动的模块的目录中搜索模块。我就是不明白其中的道理。
我不是在问如何解决这个问题。但与其说是问为什么一开始就有问题。。。
(在Python 3.8.8上测试(
它基于运行python的文件。
如果使用python c.py
运行
文件c.py使用:
from m import a, b
文件b.py也使用:
from m import a
如果你使用python b.py
,你只需要import a
就可以在b.py 中使用
因此,根据您运行的文件,它将是相对导入的父文件。
让我们从第一个工作原理开始。假设您有这样的文件结构:
c.py
m - |
|
__init__.py
a.py
b.py
假设您当前的目录在m
文件夹中,并且您运行了该命令。
python b.py
如果在您的b.py
中放置以下内容:
import a
import sys
print(sys.path)
它会很好用的。但让我们来看看print(sys.path)
的输出。在windows上,这看起来像['C:\path\to\myprogram\m', '<path to python installation>', etc.]
重要的是m
文件夹在sys.path
上,这就是解决import a
的方法。
然而,如果我们上升一个级别并运行:
python c.py
您应该立即注意到m
不再在您的sys.path
上,而是由'C:\path\to\myprogram'
替换。
这就是它失败的原因。Python会自动将您当前的工作目录包含在sys.path
中,更改它意味着它不再知道在哪里查找导入。
这是一个绝对重要的例子。您可以通过修改sys.path
以包含要导入的文件的路径来操作python查找这些导入的位置。
sys.path.append('C:\path\to\myprogram\m')
但有一个更好的方法。如果m
是一个包或子包(包括一个__init__.py
(,则可以使用相对导入。
from . import a
然而,有一个小小的警告。只有当使用相对导入的文件作为模块或包运行时,才能使用相对导入。
因此,将它们直接作为顶级脚本运行
python b.py
将产生
ImportError: attempted relative import with no known parent package
幸运的是,Python能够将脚本作为内置模块运行。如果您将cd
提升一级以便封装您的m
包,则可以运行
python -m m.b
让它运行得很好。
此外,由于import
,b.py
被视为c.py
中的一个模块,因此在这种情况下,相对导入也会起作用。
python c.py