模块
模块的概述
在Python中可以使用以下三种方法导入模块或者模块中的函数。
- import 模块名
- import 模块名as新名字
- from 模块名import函数名
自己编写模块
【实例8-2】自己编写一个模块,然后导入并调用其中的函 数,代码如下:
#模块文件
#文件名称:module_test.py
print ('导入的测试模块的输出') #被导入时会被执行,输出信息
name = 'module_test' #定义一个变量
def m_t_pr(): #模块中的函数定义
print ('模块module_test中m_t_pr()函数')
#调用自己编写的模块
#文件名:a8_2.py
import module_test #导入模块
module_test.m_t_pr() #调用导入模块的函数
print ('使用module_test模块中的变量:',module_test.name) #使用导入模块中的
【代码说明】代码其实是保存在两个文件中的,在被使用为模块的 文件代码中首先输出本模块信息,然后定义了一个变量和一个函数。导 入模块后的代码只有两行,第一行是调用导入模块中的函数,第二行直 接输出导入模块中的变量。
【运行效果】如图所示,第一行的输出实际上是导入 module_test模块时,执行模块module_test的输出(module_test.py代码中 第一行),第二行为调用module_test模块中的m_t_pr()函数的输出。
模块位置
模块的查找路径在Python中可以通过sys模块来进行操纵(查看、增 加和删除),代码如下:
import sys #导入sys模块
print (sys.path) #输出当前模块查找路径(列表形式)
sys.path.append (Apath) #添加Apath为模块查找路径
例子:
#模块文件
#文件名称:module\module_test.py
print ('导入的测试模块的输出') #被导入时会被执行,输
name = 'module_test' #定义一个变量
def m_t_pr(): #模块中的函数定义
print ('模块module_test中m_t_pr()函数')
#调用自己编写的模块
#文件名:a8_2.py
import sys #导入sys模块
sys.path.append ('D:\\lx\\module') #添加模块查找路径
import module_test #导入module_te
module_test.m_t_pr() #调用导入模块的函
print ('使用module_test模块中的变量:',module_test.name) #使用导
注:添加模块查找路径时使用绝对路径。
_pycache_目录
由于Python是脚 本,如果不想将源文件发布,可以将发布编译后的程序,这样可以起到 一定的保护源文件的作用。
对于不作为模块的程序,Python不会在运行脚本后将其编译成字节 码的形式。如果想将其编译,可以使用compile模块。如下代码可以将 上一节中的a8_2.pyc编译成“.pyc”文件。
# file: compile.py
#
import py_compile; # 导入py_compile模块
py_compile.compile(' a8_2.py',' a8_2.pyc'); # 编译a8_2.py
运行compile.py后,可以看到当前目录中多了一个a8_2.pyc文件。在 Python 3中,如果在py_compile.compile函数中不指定第2个参数,则将 在当前目录新建一个名为“__pycache__”的目录,并在这个目录中生 成“被编译模块名.cpython-32.pyc”的pyc字节码文件。运行a8_2.pyc后输出和图8.2是相同的,编译后生成的a8_2.pyc并没 有改变程序功能,只是以Python字节码的形式存在。
另外可以通过Python的命令行选项将脚本优化编译。Python编译的 优化选项有以下两个。
- -O 该选项对脚本的优化不多,编译后的脚本以“.pyo”为扩展名。 凡是以“.pyo”为扩展名的Python字节码都是经过优化的。
- -OO 该选项对脚本优化的程度较大。使用该标志可以使用编译的 Python脚本更小。使用该选项可以导致脚本运行错误,因此,应谨 慎使用。
可以通过在命令行中输入以下命令将a8_2.py优化编译。
- python -O compile.py
- python -OO compile.py
具有独立运行能力的模块
在Python中,如果程序作为模块被导入,则其__name__属性被设置 为模块名。如果程序独立运行,则其__name__属性被设置 为“__main__”。因此可以通过__name__属性来判断程序的运行状态。
对上述例子代码进行修改,它既可以独立运行,又可以作为模块被其他程序导入使用,修改后代码如下:
#模块文件
#文件名称:module\module_test.py
print ('导入的测试模块的输出') #被导入时会被执行,输出信息
name = 'module_test' #定义一个变量
def m_t_pr(): #模块中的函数定义
print ('模块module_test中m_t_pr()函数')
if __name__ == '__main__':
m_t_pr()
print (name)
一般来说,将模块的主要功能以实例的形式放在这个if语句中,可以方便测试模块是否能正常运行,或者发现模块的错误。当然这是一个好习惯,如果作为一个主程序,也可以不使用它。
此外,如果想了解模块中所提供的功能(变量名、函数名),可以使用内建的函数dir(模块名)来输出模块中的这些信息,当然也可以不使用模块名参数来列出当运行时中的模块信息。
包
包的概述
当应用程序或项目具有较多的功能模块时,如果把它们都放在同一 个文件夹下,就显得不合理了。这时,可以使用Python中提供的包来管 理较多的功能模块。使用包的好处在于可以有效避免名字冲突,便于包 的维护管理
包其实就是一个文件夹或目录,但其中必须包含一个名 为“__init__.py”(init的前后均是两条下画线)的文件。“__init__.py”可 以是一个空文件,仅用于表示该目录是一个包。此外,包还可以嵌套, 即把子包放在某个包中。
包可以看作处于同一目录中的模块。在Python中首先使用目录名,然后再使用模块名导入所需要的模块。要导入子包必须依照包顺序(目 录顺序)以点分隔使用import进行导入。
例如,对于一个web项目可能的包组织结构如下:
mywebproj/
manage.py #主程序
urls.py
__init__.py
handle/
__init__.py
index.py
info.py
temple/
index.html
info.html
tools/
__init__.py
send_emal.py
graphic.py
如果在主程序中调用handle包中的index.py模块中的hdl()函数,使用 以下三种方法导入:
import handle.index #导入后应使用handle.index.hdl()调用
from handle import index #导入后应使用index.hdl()调用
from handle.index import hdl #导入后应使用hdl()调用
包的详解
当使用了包之后,包中的模块也可能需要相互引用。以如下包结构 为例:
grnd\
__init__.py
prnta
__init__.py
suba.py
sub\
__init__.py
sona.py
prntb
__init__.py
subb.py
subc.py
包中的模块要引用同一目录下的另一模块,可以直接导入。如subb.py要调用subc.py中代码,使用如下语句:
import subc
如果一个模块要调用其同级别包中的另一模块,就必须从父包上级 开始导入。如subb.py要调用suba.py中代码,使用如下语句:
from grnd.prnta import subc
如果一个模块要调用其目录下的子包中某个模块,可以使用相对导 入的方式。如suba.py要调用sona.py中的代码,使用如下语句:
from .sub import sona
Python常用标准库简介
数学类模块
此类常用的标准库有math、random。
math中有大量的常见数学计算函数,比如三角函数(sin(),cos(), tan())、反三角函数(asin(),acos(),atn())、对数函数(log(), log10(),log2()),还包括数学中的常量,如e、pi(圆周率)。
random中包含了常见的随机数生成函数,如random、randint,还包 括一些按概率生成随机数的函数如gauss等。此外还有像shuffle(乱序列 表)、choice()(从序列中随机取元素)等随机函数。
日期与时间类
此类的标准库有calendar、datetime和time三个模块。
常需要获取的时间有两种:
- time.time() #获取自初始时间至现在的秒数
- datetime.datetime.now() #获取本地的日期/时间
- datetime.datetime.utcnow() #获取当前的UTC日期/时间
此外,还可以计算时间差或者给时间加上天数、小时等来计算未来 的时间表示。