最近经常写python脚本,感觉东西多了需要把代码分割开来,方便后期维护.因此学习了下python的包相关知识.
python包与普通文件夹的区别是多了一个init.py文件.如就是最简单的包结构,init.py可以不放任何内容,仅表示他是一个包.使用这个包的时候可以直接from app import submodule
app/
__init__.py
submodule.py
init.py是这个包的初始化模块,from-import语句导入子包时需要它,可以在里面做一些初始化工作,也可以是空文件。里面定义的属性可以直接使用 顶层包.子包 的方式导入,如在目录a的init.py文件中定义init_db()方法,调用如下:
from app import a
a.init_db()
如果要实现 from app import * 的效果可以这么写
__all__ = ['submodule',...]
,将所有对外的module放到init文件的all数组中就可以了.但是不建议这样做,from *会加重debug问题的成本,不方便后面人员的维护
有了包,就要学习下包之间的import问题了.
导入模块时,是按照sys.path变量的值搜索模块,sys.path的值是包含每一个独立路径的列表,包含当前目录、python安装目录、PYTHONPATH环境变量,搜索顺序按照路径在列表中的顺序(一般当前目录优先级最高).因此自己定义的方法如果与系统的同名的话,会覆盖系统的方法.
一般在文件首部导入所有的模块,导入顺序建议如下:
* python标准库
* 第三方模块
* 应用程序自定义模块
按照python的文档,它执行了如下操作:
* 第1步,创建一个新的,空的module对象(它可能包含多个module);
* 第2步,把这个module对象插入sys.module中
* 第3步,装载module的代码(如果需要,首先必须编译)
* 第4步,执行新的module中对应的代码。
在执行第3步时,首先要找到module程序所在的位置,其原理为:
如果需要导入的module的名字是m1,则解释器必须找到m1.py,它首先在当前目录查找,然后是在环境变量PYTHONPATH中查找。 PYTHONPATH可以视为系统的PATH变量一类的东西,其中包含若干个目录。如果PYTHONPATH没有设定,或者找不到m1.py,则继续搜索 与python的安装设置相关的默认路径,在Unix下,通常是/usr/local/lib/python。
事实上,搜索的顺序是:当前路径 (以及从当前目录指定的sys.path),然后是PYTHONPATH,然后是python的安装设置相关的默认路径。正因为存在这样的顺序,如果当前 路径或PYTHONPATH中存在与标准module同样的module,则会覆盖标准module。也就是说,如果当前目录下存在xml.py,那么执 行import xml时,导入的是当前目录下的module,而不是系统标准的xml。
更加深入的说明请参考这篇文章
假设代码组织如下:
app/
pkg1/
__init__.py
submodule1.py
pkg2/
__init__.py
submoudle2.py
test.py
包内的代码系统会自动导入,那么pkag1如何导入pkg2的内容呢?
方法1.用代码导入
这里就用到sys.path
这个系统函数了,可以在pkg2的代码中将pkg1的路径加入系统搜索路径,该更改是临时的,不会污染其他模块的代码.示例如下:
parent_path = os.path.dirname(sys.path[0])
if parent_path not in sys.path:
sys.path.append(parent_path)
这段代码将上一级的所有文件都加入了系统搜索路径,因此pkg2的submoudle2就可以使用submodule1的代码了.
方法2.保存到系统路径里
在site-packages添加一个路径文件,如mypkpath.pth,必须以.pth为后缀,写上你要加入的模块文件所在的目录名称就是了。
例如:my.pth,内容如下
/Users/XXX/Documents/script/PackageStudy/dir
放到/usr/local/lib/python2.7/site-packages这里,则可以直接importdir中的模块使用.
还有一个问题是submodule1和submoudle2相互import了,这个时候移除一个导入语句,把导入语句放到函数内部,在需要的时候导入。
def test():
from pkg2 import submoudle2
submoudle2.test()
print "dd"
1.使用.pth文件扩展python环境路径
2.import语法
3.import详解