错误从何而起?
此时有这么一个目录结构
 
我们从a/b下执行python.exe ./main.py命令开始
案例: a/b/main.py导入a/package
if __name__ == "__main__":
	# 报错 ModuleNotFoundError: No module named 'package'
	import package 
	
	# 报错 ImportError: attempted relative import with no known parent package
	from ... import package 
 
开始分析问题
问题:python为什么识别不到package?或者说, 什么样的模块python可以正常导入?
 
很容易知道, 例如: import time、import random肯定能成功,不管在什么目录下都可以导入。
问题:那么为什么他们能导入?
因为这些包的目录进行在sys模块的sys.path这个列表类型的变量中存在
执行 F:\Document\研究生总汇\interview\algorithm-coding\.leetcode\other\test\a\b>python ./main.py
if __name__ == "__main__":
    import sys
    print(sys.path)
    import package
 
输出如下:
['F:\\Document\\研究生总汇\\interview\\algorithm-coding\\.leetcode\\other\\test\\a\\b', 
'E:\\MyComputerInstalledSoftwares\\anaconda3\\envs\\jupyterlab\\python39.zip', 
'E:\\MyComputerInstalledSoftwares\\anaconda3\\envs\\jupyterlab\\DLLs', 
'E:\\MyComputerInstalledSoftwares\\anaconda3\\envs\\jupyterlab\\lib', 
'E:\\MyComputerInstalledSoftwares\\anaconda3\\envs\\jupyterlab', 
'E:\\MyComputerInstalledSoftwares\\anaconda3\\envs\\jupyterlab\\lib\\site-packages', 
'E:\\MyComputerInstalledSoftwares\\anaconda3\\envs\\jupyterlab\\lib\\site-packages\\win32', 
'E:\\MyComputerInstalledSoftwares\\anaconda3\\envs\\jupyterlab\\lib\\site-packages\\win32\\lib', 
'E:\\MyComputerInstalledSoftwares\\anaconda3\\envs\\jupyterlab\\lib\\site-packages\\Pythonwin'
]
Traceback (most recent call last):
  File "F:\Document\研究生总汇\interview\algorithm-coding\.leetcode\other\test\a\b\main.py", line 4, in <module>
    import package
ModuleNotFoundError: No module named 'package'
 
第一个值得关注的点,返回列表的第一个元素为'F:\\Document\\研究生总汇\\interview\\algorithm-coding\\.leetcode\\other\\test\\a\\b',可以发现这个路径,就是我们执行 F:\Document\研究生总汇\interview\algorithm-coding\.leetcode\other\test\a\b>python ./main.py命令时,所处的路径。
结论
因此,我们可知执行的路径会被自动加入sys.path中,并且其中还包含一些python自带的工具包所处的目录。
这也是为什么同级目录下的模块导入,以及python核心包的导入没问题的原因.
问题解决
分析到此为止,很容易得到解决方案,即, 往sys.path中增加需要扫描包的所处目录。
于是得到如下的代码:
if __name__ == "__main__":
    import sys
    sys.path.append("../..")
    import package
    print("包导入成功")
 
输出:
包导入成功
 
此外,包搜索路径的添加方式,除了sys.path.append(package_or_module_dir)的方式,还有其它方式,如下。
扩展:包搜索路径的方法
推荐阅读1
 推荐阅读2



















