pythonrelativeimportpythonrelativeimport是:from.[module/package]importxxx形式。也就是说,诸如.之类的符号。or..表示当前目录和上级目录,不直接指定目录名(即package,带__init__.py)是从对应目录导入模块还是从模块导入对应目录下模块内的名称使用方式。python文件中使用相对导入的具体细节与当前文件的name属性有关。即一个文件结构如下:pack|--a.py|--b.py|--inner|--e.py|--f.pyback|--c.py|--d.py如果在a.py中我们有:from.bimportfuncprint(__name__)运行a.py的结果是在import语句处产生错误。当然,print(__name__)这一步是不会执行的,但是它的结果是__main__。这是因为我们直接执行a.py作为入口脚本,它的__name__是__main__,没有层级结构。对于相对进口,其.matches无法从当前的__name__解析出有效结果。这是语法分析角度的问题,所以使用相对导入的python脚本不能作为入口脚本直接执行。那么如果我们在a.py中这样导入呢?frombackimportcprint(__name__)和c.py如下:from.importdprint(__name__)所以我们不直接运行使用相对导入的python脚本文件,在a.py中我们以如下形式导入cfrombackimportc,那么c的__name__属性应该是back.c,进一步使用from应该是可行的。在c.py中importd,即可成功解析name。试过这样运行a.py,结果还是报错,a.py里面有错误,报错显示nomodulenamedback。这就涉及到python导入模块时的搜索问题。python的sys模块中sys.path的一个方法:sys.path。它返回一个列表,列表中的每一项都是导入python文件时的搜索路径。值得注意的是:1.sys.path是程序启动时初始化的,sys.path[0]表示启用python解释器的脚本所在目录。如果该目录不可用(例如,交互调用解释器,或者脚本从标准输入读取),那么sys.path[0]是一个空字符串,表示python首先在当前工作目录中搜索模块。【这也就解释了为什么上面第二次尝试失败了,因为后面的目录不在sys.path列表中】2.除了sys.path[0],其余的sys.path列表项一般都是python的路径标准库和一些第三方包。并且我们也可以在导入其他模块之前先导入sys,修改、添加或删除sys.path。3.sys.path以入口python脚本为准,即如果有导入的模块tmp,如果该模块中还导入了其他模块,那么此时以入口脚本的sys.path为准当tmp模块用作入口脚本时,不是sys.path。这主要与第一点中sys.path[0]的问题有关。那我们再试一次,回忆一下这里的目录结构:pack|--a.py|--b.py|--inner|--e.py|--f.pyback|--c.py|---d.py我们在a.py中如下:frominnerimporteprint(__name__)ine.pyunderinneris:from.importfprint(__name__)所以我们再次运行a.py,结果是:inner.e__main__其中inner.e是e.py的__name__,__main__是a.py的__name__,运行成功。即sys.path[0]是a.py所在的目录路径,在这个路径下可以找到inner目录,那么e.py就可以顺利的从inner导入,e.py的__name__也有Hierarchical,语法解析没有问题。提示:在e.py中我们有from.importf,但是可以写成from..importb吗?答案是否定的,假设e.py中的__name__是inner.e,所以from.解析语法时在对应的__name__中是inner,在inner.e中找不到..,即__name__不是pack.inner.e,所以..对应的语法解析会失败。python-m除了直接运行python文件中的脚本外,还可以在命令行中以pythonxxx.py的形式直接运行脚本。那么python-m是做什么的呢?命令行下的帮助是这样写的:runlibrarymoduleasascript。网上大部分博客都说python脚本是作为模块运行的。两种解释似乎有些矛盾。其实这些说法大可不必理会。运行python-m和直接运行python有两个主要区别:1.直接运行python的脚本是pythontmp.py的形式,如果有目录结构的话是pythonparent/的形式tmp.py。python-m操作的形式是python-mtmp,如果有目录结构,对应的形式是python-mparent.tmp。2、pythontmp.py对应的sys.path[0]是tmp.py所在的目录路径,即使是pythonparent/tmp.py。python-m的sys.path[0]是命令执行的路径,比如python-mtmp,这个路径也是tmp.py文件所在的路径,没有区别。但是对于python-mparent.tmp,对应的路径是父目录所在的路径,而不是tmp.py所在的路径。对于上面的第二点,我们再举一个例子。这里回顾一下我们的目录结构,给出上层目录:direct|---pack|--a.py|--b.py|--inner|--e.py|--f.py|---back|--c.py|--d.py让我们回到上面的第二次尝试,在a.py中:frombackimportcprint(__name__)inc.py:from。importdprint(__name__)如果我们直接运行a.py或者pythona.py会出错,因为back不在sys.path中。然后我们直接回到上层目录,使用python-mpack.a就可以顺利运行了。原因是因为python-m的sys.path[0]并不是入口脚本所在的路径,而是命令所在目录的路径。
