Python中模块与包有相同名字的处理方法
前言
在编程开发中,个人觉得,只要按照规范去做,很少会出问题。刚开始学习一门技术时,的确会遇到很多的坑。踩的坑多了,这是好事,会学到更多东西,也会越来越觉得按照规范做的重要性,规范的制定就是用来规避问题的。有时候确实应该听听有经验人的建议,不要一意孤行。这好像不是本文的重点,其实我重点是想表达,尽量按规范做事,这样会少走很多弯路。
我现在使用的主力编程语言是Python,在接触Python至今,我感觉我踩的坑还是极少的,基本上没有遇到什么奇怪的问题。实际上,这并不是一件好事,不踩坑,很多躺在暗处的知识点你不会了解,所以也很难成长。幸好,有一些会踩坑的同事。
一同事问我,在Python中,如果一个模块和一个包同名时,是不是只能导入包,如果要导入模块该怎么办。他的意思大概是这样的,在项目的同一级目录下,有一个foo.py文件和一个foo/目录,如果importfoo会导入foo/的内容而不是foo.py的内容。
被问到这个问题时,我首先感觉到的是诧异,这明显是存在歧义的。如果是我,肯定不会把模块名和包名设计成一样的名字,因为本质上来说在导入的时候没法区分到底要导入谁。除非系统有特别的规定,例如,规定这种情况只能导入包。
我的潜意识里认为这里应该报错,Python解释器不知道要导入谁。但是,同事告诉我,别人的代码是这么写的,而且在这种情况下会默认导入包。那就是可以的咯,而且解释器已经规定这种情况会总是导入包。
为了验证下这一点,我写了个简单的项目,项目结构如下:
. ├──main.py └──same ├──api │└──__init__.py ├──auth │└──__init__.py ├──auth.py └──__init__.py
其中:
same/api/__init__/py的内容:
from..importauth
same/auth/__init__.py的内容:
auth_str="Thisisstrinpackage!"
same/auth.py的内容:
auth_str="Thisisstrinmodule!"
main.py的内容:
from__future__importprint_function fromsame.apiimportauth #Scriptstartsfromhere if__name__=="__main__": print(auth.auth_str)
稍微有些复杂,哈哈,主要是同事那儿大致的结构是这样的,这里是为更好的模拟下。我在same.auth包中定义了一个auth_str字符串,又在同名的same.auth模块中定义了一个同名的auth_str字符串,然后在same.api包尝试导入auth,最后在main.py尝试输出same.api.auth.auth_str,看看到底哪个字符串会被打印。同时尝试用Python2和Python3执行main.py,得到的结果都是:
Thisisstrinpackage!
这里验证了我们的猜想是正确的,解释器的确只导入了包中内容。但是,我并不知道是否有官方的资料说明就是这样的,所以我不敢确信,万一这只是巧合呢。
于是,我开始查资料来验证这一结论。我就说实话吧,对于一个英文水平烂到你无法想象的我,只能先尝试用百度搜索下答案了。事实是,用百度往往都是遗憾的。片刻后,无果,我只能硬着头皮尝试英文搜索了。于是,在stackoverflow上找到了如下提问:
Howpythondealswithmoduleandpackagehavingthesamename?
其中有一个人回答说Python官方文档中在描述模块搜索路径时提到了这一点:https://docs.python.org/3/tutorial/modules.html#the-module-search-path.
文档中有如下一段描述:
Afterinitialization,Pythonprogramscanmodifysys.path.Thedirectorycontainingthescriptbeingrunisplacedatthebeginningofthesearchpath,aheadofthestandardlibrarypath.Thismeansthatscriptsinthatdirectorywillbeloadedinsteadofmodulesofthesamenameinthelibrarydirectory.Thisisanerrorunlessthereplacementisintended.SeesectionStandardModulesformoreinformation.
也就是说,目录在库的搜索路径下会首先被搜索,这就意味着目录会代替同名的模块被加载。
这下终于放心了,之前的结论得到证实。在Python中,如果尝试导入同名的模块和包时,包会被导入。这种情况下,如果想要导入模块,恐怕要用一些‘hack'的方法,上面提到的stackoverflow帖下有一些示例可以参考。当然,最好的方法是避免这样的设计,这样你就不会花那么长时间去查资料,也不会花那么长时间来写类似于本文的文章。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。