模块与包

模块

一个模块就是一个包含了一组功能的python文件,比如spam.py,模块名为spam,可以通过import spam使用。

 

模块的4种存在方式

1.使用c编写并链接到python解释器的内置模块

2.使用python编写的。py文件

3.包:一堆py文件集合体

q4.已被编译为共享库或dll的c或c++扩展

 

导入模块

1.编译执行模块所对应的py文件,形成对应的pyc文件

2.产生该模块自家的全局名称空间

3.在使用该模块的全局名称空间中产生一个名字(导入的模块名)

以spam.py为例来介绍模块的使用:文件名spam.py,模块名spam

#spam.py
print('from the spam.py')

money=1000

def read1():
    print('spam模块:',money)

def read2():
    print('spam模块')
    read1()

def change():
    global money
    money=0

 

 import

通过import关键字导入模块名

 

“import”是引入一个完整的模块,“from…import”是引入模块中的一个或多个指定部分;

“import”引入模块后,如果需要使用模块里的函数方法,则需要加上模块的限定名字,“from...import”则不用加模块的限定名字,直接使用其函数方法;

 

 

import module

编译执行模块所对应的py文件,形成对应的pyc文件

产生该模块自己的全局名称空间

在使用该模块的全局名称空间中产生一个名字(导入的模块名)

 

优点:

1.从文件级别组织代码,是同特性的功能能统一管理

2.可以使用系统或第三方模块(拿来主义),来提高开发效率

 

 被导入模块有独立的名称空间

每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突

#test.py
import spam 
money=10
print(spam.money)

'''
执行结果:
from the spam.py
1000
'''

 

为模块名起别名

为已经导入的模块起别名的方式对编写可扩展的代码很有用

1 import spam as sm
2 print(sm.money)

 

模块之from ... import...

from模块名 import*

导入的是模块中的_all_这个列表

1.系统默认该列表不会收录开头的名字

2.可以自定义_all_列表来规定外界通过*可以导入的名字

 

from 模块名 import 名字1,名字2,。。。,名字n

可以指名道姓导入模版中所有想导入的名字

 

测试一:导入的函数read1,执行时仍然回到spam.py中寻找全局变量money
#test.py
from spam import read1
money=1000
read1()
'''
执行结果:
from the spam.py
spam->read1->money 1000
'''

#测试二:导入的函数read2,执行时需要调用read1(),仍然回到spam.py中找read1()
#test.py
from spam import read2
def read1():
    print('==========')
read2()

'''
执行结果:
from the spam.py
spam->read2 calling read
spam->read1->money 1000

 

 py文件区分两种用途:模块与脚本

编写好的一个python文件可以有两种用途:
    一:脚本,一个文件就是整个程序,用来被执行
    二:模块,文件中存放着一堆功能,用来被导入使用
python为我们内置了全局变量__name__,
    当文件被当做脚本执行时:__name__ 等于'__main__'
    当文件被当做模块导入时:__name__等于模块名

#作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
    if __name__ == '__main__':
复制代码

 

logging 模块

logging模块是python提供的用于记录日志的模块

 日志级别

在开始记录日志前还需要明确,日志的级别

随着时间的推移,日志记录会非常多,成千上万行,如何快速找到需要的日志记录这就成了问题

解决的方案就是 给日志划分级别

logging模块将日志分为了五个级别,从高到低分别是:

1.info 常规信息

2.debug 调试信息

3.warning 警告信息

4.error 错误信息

5.crtical 严重错误

本质上他们使用数字来表示级别的,从高到低分别是10,20,30,40,50

 

模块搜索路径

模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块

 

模块的查找顺序
1、在第一次导入某个模块时(比如spam),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用
    ps:python解释器在启动时会自动加载一些模块到内存中,可以使用sys.modules查看
2、如果没有,解释器则会查找同名的内建模块
3、如果还没有找到就从sys.path给出的目录列表中依次寻找spam.py文件。



包是一种通过使用‘.模块名’来组织python模块名称空间的方式。
包就是一个包含有__init__.py文件的文件夹,所以其实我们创建包的目的就是为了用文件夹将文件/模块组织起来

包的本质就是一个文件夹,那么文件夹唯一的功能就是将文件组织起来
随着功能越写越多,我们无法将所以功能都放到一个文件中,于是我们使用模块去组织功能,而随着模块越来越多,我们就需要用文件夹将模块文件组织起来,以此来提高程序的结构性和可维护性
#文件内容

#policy.py
def get():
    print('from policy.py')

#versions.py
def create_resource(conf):
    print('from version.py: ',conf)

#manage.py
def main():
    print('from manage.py')

#models.py
def register_models(engine):
    print('from models.py: ',engine)

 包的使用 import

1 import glance.db.models
2 glance.db.models.register_models('mysql') 

 

包的使用之from ... import ...

需要注意的是from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法

1 from glance.db import models
2 models.register_models('mysql')
3 
4 from glance.db.models import register_models
5 register_models('mysql')

 

from glance.api import *

在讲模块时,我们已经讨论过了从一个模块内导入所有*,此处我们研究从一个包导入所有*。

 #在__init__.py中定义
2 x=10
3 
4 def func():
5     print('from api.__init.py')
6 
7 __all__=['x','func','policy']

 

绝对导入和相对导入

我们的最*包glance是写给别人用的,然后在glance包内部也会有彼此之间互相导入的需求,这时候就有绝对导入和相对导入两种方式:

绝对导入:以glance作为起始

相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)

例如:我们在glance/api/version.py中想要导入glance/cmd/manage.py

 在glance/api/version.py
2 
3 #绝对导入
4 from glance.cmd import manage
5 manage.main()
6 
7 #相对导入
8 from ..cmd import manage
9 manage.main()

 

绝对导入: 以执行文件的sys.path为起始点开始导入,称之为绝对导入
        优点: 执行文件与被导入的模块中都可以使用
        缺点: 所有导入都是以sys.path为起始点,导入麻烦

 相对导入: 参照当前所在文件的文件夹为起始开始查找,称之为相对导入
        符号: .代表当前所在文件的文件加,..代表上一级文件夹,...代表上一级的上一级文件夹
        优点: 导入更加简单
        缺点: 只能在导入包中的模块时才能使用

模块与包


上一篇:从PHP访问Gmails SPAM文件夹


下一篇:php – 反对人力支付的垃圾邮件发送者