【大数据课堂0003】【import】__file__ 作用以及模块导入方法
【原理】import 导入模块,就是能够根据sys.path环境变量的值,找到具体模块的路径。
import上一级目录的模块===>
sys.path.insert(0,'../') #最简洁做法
python 执行py 文件的时候,默认就会把当前目录增加到sys.path中。sys.path[0]。
– src |– mod1.py |– test1.py test1.py中导入模块mod1, 则直接使用 import mod1 或 from mod1 import *
– src |– mod1.py |– mod2 | – mod2.py – test1.py from mod2.mod2 import * 或 import mod2.mod2.
– src |– mod1.py |– mod2 |– mod2.py |– sub | – test2.py – test1.py #test2.py 调用模块 import sys
sys.path.insert(0,'../')# 简洁 ..==../
#parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
#sys.path.insert(0,parentdir)
import mod1
import mod2.mod2
python中,import module会去sys.path搜索,sys.path是个列表,并且我们可以动态修改。
要import某个目录的module,我们sys.path.insert(0,somedir)来加入搜索路径,就可以import了。
既然这样,要import上一级目录的module,可以sys.path.insert(0,parentdir)。
不过这种写绝对路径的方式,如果文件放到其它地方,就不行了。
所以用动态方法来获取上一级目录。当前文件执行的目录的路径就加入到python 路径里面,后面不管你目录移动到什么位置,里面的文件都能执行。
__file__:当前执行的文件,不带路径,除非自己带路径。Python a.py __file__==a.py ; python D:/b.py __file__==D:/b.py
import os,sys parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0,parentdir)
为什么用sys.path.insert(0,parentdir) 而不是用sys.path.append(parentdir)呢
因为是遍历搜索路径的,所以如果在其它路径里也有个同名的module,会import错。用sys.path.insert(0,parentdir)可以确保先搜索这个路径;2,自定义的优先级要高,保证优先搜到。
解决循环import的问题: A中导入B ,B 也需要A中内容。----理顺逻辑,组织代码
# 不能逻辑不清晰,循环死调用,a里调b b里有调a
在python中常常会遇到循环import即circular import的问题。
现实中经常出现这种滑稽的情况,
安装无线网卡的时候,需要上网下载网卡驱动..
这样就产生了循环import的问题。
解决循环import的方法主要有几种。
1.延迟导入(lazy import)
即把import语句写在方法或函数里面,将它的作用域限制在局部。
这种方法的缺点就是会有性能问题。
2.将from xxx import yyy改成import xxx;xxx.yyy来访问的形式
3.组织代码
出现循环import的问题往往意味着代码的布局有问题。
可以合并或者分离竞争资源。
合并的话就是都写到一个文件里面去。
分离的话就是把需要import的资源提取到一个第三方文件去。
总之就是将循环变成单向。
原理:
原来在python模块的每一个包中,都有一个__init__.py文件(这个文件定义了包的属性和方法)然后是一些模块文件和子目录,假如子目录中也有 __init__.py 那么它就是这个包的子包了。当你将一个包作为模块导入(比如从 xml导入 dom )的时候,实际上导入了它的 __init__.py 文件。
一个包是一个带有特殊文件 __init__.py 的目录。__init__.py 文件定义了包的属性和方法。其实它可以什么也不定义;可以只是一个空文件,但是必须存在。如果 __init__.py 不存在,这个目录就仅仅是一个目录,而不是一个包,它就不能被导入或者包含其它的模块和嵌套包。
_init__.py 文件:
__init__.py 控制着包的导入行为。假如 __init__.py 为空,那么仅仅导入包是什么都做不了的。
__init__.py 中还有一个重要的变量,叫做 __all__。我们有时会使出一招“全部导入”,也就是这样:
这时 import 就会把注册在包 __init__.py 文件中 __all__ 列表中的子模块和子包导入到当前作用域中来。比如:
__init__.py 文件会在导入时被执行。