在python中,文件名也会作为模块的名称使用。
举个例子
工程目录如下:
其中,文件夹为sys_check,其下还有一个sys_check1.py文件。
如果该文件名也是sys_check.py,可能会导致问题,在其它文件中引用模块时会出错。
比如,在kernel_version.py中引用common_data中的内容时:
from sys_check.common_data import *
会报如下错误:
ModuleNotFoundError: No module named 'sys_check.common_data';
'sys_check' is not a package
原因分析
在Python中,当我们尝试导入一个模块时,Python解释器会按照特定的顺序搜索模块。这个过程涉及到搜索路径(sys.path),包括:
- 当前目录
- PYTHONPATH环境变量指定的目录
- Python安装的site-packages目录等。
当我们有一个目录和一个文件同名的情况,比如一个名为sys_check的目录和一个名为sys_check.py的文件,Python解释器在导入时会根据以下规则来处理:
文件优先
如果存在一个与模块名相同的.py文件,Python解释器会优先加载这个文件作为模块。这意味着如果有一个名为sys_check.py的文件,尝试导入sys_check时,Python会加载这个文件,而不是目录。
目录作为包
如果目录中包含一个__init__.py文件(可以是空的),Python解释器会将该目录视为一个包。这样,我们就可以从这个包中导入子模块。例如,如果sys_check目录包含__init__.py文件,那么我们可以从这个目录中导入common_data模块。
在上述提供的场景中,如果sys_check目录下有一个sys_check.py文件,当我们尝试执行以下导入语句:
from sys_check.common_data import *
Python解释器会首先查找名为sys_check.py的文件,因为它与模块名相同。由于找到了这个文件,它不会继续搜索同名的目录。这意味着sys_check目录被忽略了,即使它可能是一个包含__init__.py的包,其中可能包含common_data模块。
这就是为什么我们会收到上述错误,因为Python解释器没有将sys_check目录视为一个包,而是将sys_check.py文件作为模块加载了。
解决办法
重命名文件或目录
确保目录和文件不要同名,这样可以避免冲突。如果sys_check是一个目录,并且我们希望它作为一个包来使用,那么不要在这个目录下创建同名的sys_check.py文件,比如改成sys_check1.py,当然文件名加1并不是一个好的做法,可以改成system_check.py等。
确保目录是包
如果sys_check目录应该是一个包,确保它包含一个__init__.py文件。这样,即使目录和文件名不同,我们也可以正确地从sys_check包中导入common_data模块。
通过这种方式,我们可以避免导入时的命名冲突,并确保Python解释器能够正确地识别和加载我们的模块和包。