从 __init__.py 文件进行相对导入时抛出错误
我正在使用一个同事设置的模板,作为一个Python新手,我可能错过了一些很明显的东西。
主目录里有一个init文件,这个文件里有我需要的模块,而这个模块在生成错误的主Python文件中。
同事使用了:
from . import X
这里的X是模块名,但当我把这个(还有一个已经填充好的init文件)复制到我自己的目录时,就出现了这个错误:
ValueError: 尝试在非包中进行相对导入
从谷歌和StackOverflow上我了解到,这种情况是完全可以理解的,所以作为新手的我想知道,我到底错过了什么。
1 个回答
你需要了解Python是如何处理模块的。
当你用一个脚本启动解释器时,这个脚本就变成了主模块,名字叫__main__
。
使用import
时,Python会在一个搜索路径中查找其他模块。你可以通过sys.path
来访问和修改这个路径。sys.path
的第一个条目通常是空的,表示当前目录。
如果一个目录里有一个__init__.py
文件,那么这个目录就被认为是一个包。
现在,当你在一个包含__init__.py
文件的目录中执行一个脚本时,这个脚本会成为__main__
,而这个目录不会被视为包,因为它不在sys.path
中!
举个例子,考虑下面的目录结构:
root/ pkg/ __init__.py b.py c.py a.py
当你从root/
目录运行python a.py
时,你可以导入pkg/
,并在这个包内使用相对导入(比如在b.py
或__init__.py
中使用from . import c
)。
但是,当你从pkg
目录运行python b.py
时,你就不能使用相对导入了,因为Python不把pkg
当作一个包:它不在sys.path
中。对于Python来说,pkg
只是一个普通的目录,不管它里面是否有__init__.py
。c.py
的完整名称就是c
,而不是pkg.c
,所以from . import c
这样的相对导入是行不通的。