最近从python2转到python3,发现还是有一些不同,一些库改名字很好解决,但是这个import机制不了解原理是不好理解的.
python2是默认相对路径导入,python3是默认绝对路径导入 #
首先这个包的导入机制,就是你在一个module里面引用另一个module,python运行文件有两种方式,一种是直接以主文件运行(默认以这种方式运行,同下面一种有点区别),一种是以module形式运行,就是用python -m filename
方式调用.
以module的方式运行 #
####### 什么是相对导入和绝对导入呢
相对导入是用一个.
来声明的,相当于Unix上的选择当前文件夹.
假设你的文件目录为下面的
main
| main.py
| __init__py
| momod+
| | __init__.py
| | pack.py
| | flask
| | | __init__.py
| | | myflask.py
--------------------
python里面的module分三种,一种是build-in module(内建库),一种是第三方库,还有一种是你自己写的库(如上面的flask). #
在python2里面,当你import 一个module时,搜索的顺序是 内建库,自己的库,第三方库.
####### 而在python3里面顺序为 内建库,第三方库,你自己的库.
我自己感觉python3的import的机制更为清晰,因为当你import一个库时,假如你写的库和第三方库重合时,你优先导入第三方库,如果你不适用声明相对导入的话,你无法正确的导入自己的库,而使用.
来声明库来自自己的代码让代码的结构更加清晰了.所以如果你想让你的代码兼容py2和py3,你自己的库都要采用相对导入方法来导入.
比如在momod 里面的pack.py假如想引用flask的myflask.py要这样写
from .flask import myflask
########### 假如你在py2中写了 from flask import myflask
(并且你安装了flask库),这个是可以成功运行但是在py3中就会报错,因为他会优先导入flask库假如你没有显示声明相对导入的话.
上面成立的前提是将pack.py以module方式运行,或者运行main.py在其中引入pack.py.接下来讲讲以主文件运行的不同.
当你直接使用 #
python pack.py
你假如在pack.py里面使用了这个
from .flask import myflask
引用了自己的myflaskmodule,在py2和py3中都会下面报这个错
SystemError: Parent module '' not loaded, cannot perform relative import
因为当你以主文件方式运行 pack.py ,python会吧pack.py重命名为__main__
,所以用.相对路径也不会是当前文件.所以全部都只能用绝对引用.所以在主文件运行在python3里面有个问题,假如你自己的库与第三方库有重名.
python3默认绝对路径,自己的库不会优先于第三方库被扫描.有两个解决方法,把自己的库重命名,第二个方法就是把包含主文件的文件夹加上__init__.py,你可以在sys.path的路径里加上..
或者具体上一个上一个文件夹的路径.怪绕口的,其实你只要python能找到你的上一个文件夹,就行.
#
说到这里顺便插一句对doctest和集成测试的理解.
由于我平时喜欢一边写代码一遍测试功能,图方便就使用doctest直接插在方法里面,在代码后面加上 #
if __name__ == '__main__':
import doctest
doctest.tesmod()
平时写小module的时候没有问题,在将python2转python3时候,出现问题,因为我要测试这个module时,会报上面的那个错,因为我要测试他的话必须将它作为主文件.查了资料知道,其实doctest虽然在当前页面代码测试,但是对于module的话,最好采用集成测试,一是module很多,假如一个一个运行很麻烦,二是有时候module必须多个一起测试,所以测试module时要用集成测试来取代doctest.