我正在使用一位同事提供的模板,作为 Python 新手,我可能会错过一些非常显而易见的东西。
主目录有一个 init 文件,其中包含一个我需要的模块,用于生成错误的主 Python 文件。
同事使用了:
from . import X
当X是模块时,但当我将其(以及一个填充了init文件的模块)复制到自己的目录中时,它生成以下错误:
ValueError: 尝试在非包中进行相对导入
从Google和SO中我得知这很正常和合理,所以我想知道,作为一个新手,我错过了什么。
我正在使用一位同事提供的模板,作为 Python 新手,我可能会错过一些非常显而易见的东西。
主目录有一个 init 文件,其中包含一个我需要的模块,用于生成错误的主 Python 文件。
同事使用了:
from . import X
当X是模块时,但当我将其(以及一个填充了init文件的模块)复制到自己的目录中时,它生成以下错误:
ValueError: 尝试在非包中进行相对导入
从Google和SO中我得知这很正常和合理,所以我想知道,作为一个新手,我错过了什么。
你需要了解Python如何处理模块。
当你使用脚本启动解释器时,该脚本将成为主模块,并具有相应的名称__main__
。
使用import
时,其他模块会在搜索路径中查找,你也可以使用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
将不起作用。