1. 模块简介
模块就是一个保存了 Python 代码的文件。模块能定义函数,类和变量。模块里也能包含可执行的代码。
模块也是 Python 对象,具有随机的名字属性用来绑定或引用。
下例是个简单的模块support.py
1 def print_func( par ): 2 print("Hello : ", par) 3 return
1)import 语句
想使用 Python 源文件,只需在另一个源文件里执行 import 语句,语法如下:
import module1[, module2[,... moduleN]
当解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入。
搜索路径是一个解释器会先进行搜索的所有目录的列表。如想要导入模块 support.py ,需要把命令放在脚本的顶端:
1 #!/usr/bin/env python 2 # -*- coding: UTF-8 -*- 3 4 # 导入模块 5 import support 6 7 # 现在可以调用模块里包含的函数了 8 support.print_func("Zara")
输出结果:
1 Hello : Zara
一个模块只会被导入一次,不管你执行了多少次 import ,这样可以防止导入模块被一遍又一遍地执行。
2)from … import 语句
Python 的 from 语句让你从模块中导入一个指定的部分到当前命名空间中。语法如下:
from modname import name1[, name2[, ... nameN]]
例如,要导入模块 fib 的 fibonacci 函数,使用如下语句:
from fib import fibonacci
这个声明不会把整个 fib 模块导入到当前的命名空间中,它只会将 fib 里的 fibonacci 单个引入到执行这个声明的模块的全局符号表。
3)from … import * 语句
把一个模块的所有内容全都导入到当前的命名空间也是可行的,只需使用如下声明:
from modname import *
这提供了一个简单的方法来导入一个模块中的所有项目,然而这种声明不该被过多地使用。
4)定位模块
当你导入一个模块,Python 解析器对模块位置的搜索顺序是:
- 当前目录
- 如果不在当前目录,Python 则搜索在 shell 变量 PYTHONPATH 下的每个目录
- 如果都找不到,Python 会察看默认路径。UNIX 下,默认路径一般为 /usr/local/lib/python/ 。
模块搜索路径存储在 system 模块的 sys.path 变量中。变量里包含当前目录,PYTHONPATH 和由安装过程决定的默认目录。
5) PYTHONPATH变量
作为环境变量,PYTHONPATH 由装在一个列表里的许多目录组成。PYTHONPATH 的语法和 shel l 变量的 PATH 一样。
在Windows系统,典型的PYTHONPATH如下:
1 >>> import sys 2 >>> sys.path 3 ['', 'C:\\Python35\\Lib\\idlelib', 'C:\\Python35\\python35.zip', 'C:\\Python35\\DLLs', 'C:\\Python35\\lib', 'C:\\Python35', 'C:\\Python35\\lib\\site-packages']
在UNIX系统,典型的PYTHONPATH如下:
1 >>> import sys 2 >>> sys.path 3 ['', '/usr/local/python35/lib/python35.zip', '/usr/local/python35/lib/python3.5', '/usr/local/python35/lib/python3.5/plat-linux', '/usr/local/python35/lib/python3.5/lib-dynload', '/usr/local/python35/lib/python3.5/site-packages']
6) 命名空间和作用域
变量是拥有匹配对象的名字(标识符)。命名空间是一个包含了变量名称们(键)和它们各自相应的对象们(值)的字典。
一个 Python 表达式可以访问局部命名空间和全局命名空间里的变量。
如果一个局部变量和一个全局变量重名,则局部变量会覆盖全局变量。
每个函数都有自己的命名空间。类的方法的作用域规则和通常函数的一样。
Python 会智能地猜测一个变量是局部的还是全局的,它假设任何在函数内赋值的变量都是局部的。
因此,如果要给全局变量在一个函数里赋值,必须使用 global 语句。
global VarName 的表达式会告诉 Python , VarName 是一个全局变量,这样 Python 就不会在局部命名空间里寻找这个变量了。
例如,我们在全局命名空间里定义一个变量 money ,我们再在函数内给变量 money 赋值,然后 Python 会假定 money 是一个局部变量。然而,我们并没有在访问前声明一个局部变量 money ,结果就是会出现一个 UnboundLocalError 的错误。取消 global 语句的注释就能解决这个问题。
1 >>> money = 2000 2 >>> def add_money(): 3 # 想改正代码就取消以下注释 4 # global money 5 money += 1 6 7 8 >>> print(money) 9 2000 10 >>> add_money() 11 Traceback (most recent call last): 12 File "<pyshell#7>", line 1, in <module> 13 add_money() 14 File "<pyshell#5>", line 4, in add_money 15 money += 1 16 UnboundLocalError: local variable 'money' referenced before assignment 17 >>> print(money)
取消注释:
1 >>> money = 2000 2 >>> def add_money(): 3 global money 4 money += 1 5 6 7 >>> print(money) 8 2000 9 >>> add_money() 10 >>> print(money) 11 2001
7)Python 中的包
包是一个分层次的文件目录结构,它定义了一个由模块及子包,和子包下的子包等组成的 Python 的应用环境。
考虑一个在 Phone 目录下的 pots.py 文件。这个文件有如下源代码:
1 #!/usr/bin/env python 2 # -*- coding: UTF-8 -*- 3 4 def Pots(): 5 print("I'm Pots Phone")
同样地,我们有另外两个保存了不同函数的文件:
- Phone/Isdn.py 含有函数 Isdn()
- Phone/G3.py 含有函数 G3()
现在,在 Phone 目录下创建file __init__.py:
- Phone/__init__.py
当你导入 Phone 时,为了能够使用所有函数,你需要在 __init__.py 里使用显式的导入语句,如下:
from Pots import Pots from Isdn import Isdn from G3 import G3
当你把这些代码添加到 __init__.py 之后,导入Phone包的时候这些类就全都是可用的了。
1 #!/usr/bin/python 2 # -*- coding: UTF-8 -*- 3 4 # 导入 Phone 包 5 import Phone 6 7 Phone.Pots() 8 Phone.Isdn() 9 Phone.G3()
输出结果:
1 I'm Pots Phone 2 I'm 3G Phone 3 I'm ISDN Phone
如上,为了举例,我们只在每个文件里放置了一个函数,但其实你可以放置许多函数。
也可以在这些文件里定义Python的类,然后为这些类建一个包。
8) dir() 函数
dir() 函数一个排好序的字符串列表,内容是一个模块里定义过的名字。
返回的列表容纳了在一个模块里定义的所有模块、变量和函数。
如下一个简单的实例:
1 #!/usr/bin/env python 2 # -*- coding: UTF-8 -*- 3 4 # 导入内置 math 模块 5 import math 6 7 dir(math)
以上实例输出结果:
1 ['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
在这里,特殊字符串变量 __name__ 指向模块的名字,__file__ 指向该模块的导入文件名。
9) globals() 和 locals() 函数
根据调用地方的不同,globals() 和 locals() 函数可被用来返回全局和局部命名空间里的名字。
如果在函数内部调用 locals() ,返回的是所有能在该函数里访问的命名。
1 >>> locals() 2 {'__spec__': None, '__name__': '__main__', '__doc__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__builtins__': <module 'builtins' (built-in)>, 'math': <module 'math' (built-in)>, '__package__': None}
如果在函数内部调用 globals(),返回的是所有在该函数里能访问的全局名字。
1 >>> globals() 2 {'__spec__': None, '__name__': '__main__', '__doc__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__builtins__': <module 'builtins' (built-in)>, 'math': <module 'math' (built-in)>, '__package__': None}
两个函数的返回类型都是字典,所以名字能用 keys() 函数获取。
10) reload() 函数
当一个模块被导入到一个脚本,模块顶层部分的代码只会被执行一次。
因此,如果你想重新执行模块里顶层部分的代码,可以用 reload() 函数。
该函数会重新导入之前导入过的模块。语法如下:
reload(module_name)
在这里,module_name 要直接放模块的名字,而不是一个字符串形式。比如想重载 hello 模块,如下:
reload(hello)
2. 常用模块
1) time & calendar & datetime
Python 日期和时间
Python 程序能用很多方式处理日期和时间,转换日期格式是一个常见的功能。
Python 提供了一个 time 和 calendar 模块可以用于格式化日期和时间。
时间间隔是以秒为单位的浮点小数。
每个时间戳都以自从1970年1月1日午夜(历元)经过了多长时间来表示。
Python 的 time 模块下有很多函数可以转换常见日期格式。如函数time.time()用于获取当前时间戳, 如下实例:
1 #!/usr/bin/env python 2 # -*- coding: UTF-8 -*- 3 4 import time # 引入time模块 5 6 ticks = time.time() 7 print("当前时间戳为:", ticks)
输出结果:
1 当前时间戳为: 1479129524.694309
时间戳单位最适于做日期运算。但是1970年之前的日期就无法以此表示了。太遥远的日期也不行,UNIX和Windows只支持到2038年。
时间元组
很多Python函数用一个元组装起来的9组数字处理时间:
序号 | 字段 | 值 |
---|---|---|
0 | 4位数年 | 2008 |
1 | 月 | 1 到 12 |
2 | 日 | 1到31 |
3 | 小时 | 0到23 |
4 | 分钟 | 0到59 |
5 | 秒 | 0到61 (60或61 是闰秒) |
6 | 一周的第几日 | 0到6 (0是周一) |
7 | 一年的第几日 | 1到366 (儒略历) |
8 | 夏令时 | -1, 0, 1, -1是决定是否为夏令时的旗帜 |
上述也就是struct_time元组。这种结构具有如下属性:
序号 | 属性 | 值 |
---|---|---|
0 | tm_year | 2008 |
1 | tm_mon | 1 到 12 |
2 | tm_mday | 1 到 31 |
3 | tm_hour | 0 到 23 |
4 | tm_min | 0 到 59 |
5 | tm_sec | 0 到 61 (60或61 是闰秒) |
6 | tm_wday | 0到6 (0是周一) |
7 | tm_yday | 1 到 366(儒略历) |
8 | tm_isdst | -1, 0, 1, -1是决定是否为夏令时的旗帜 |
获取当前时间
从返回浮点数的时间辍方式向时间元组转换,只要将浮点数传递给如localtime之类的函数。
1 #!/usr/bin/env python 2 # -*- coding: UTF-8 -*- 3 4 import time 5 6 localtime = time.localtime(time.time()) 7 print("本地时间为 :", localtime)
输出结果:
1 本地时间为 : time.struct_time(tm_year=2016, tm_mon=11, tm_mday=14, tm_hour=21, tm_min=21, tm_sec=2, tm_wday=0, tm_yday=319, tm_isdst=0)
获取格式化的时间
可以根据需求选取各种格式的时间,但是最简单的获取可读时间模式的函数是asctime():
1 #!/usr/bin/env python 2 # -*- coding: UTF-8 -*- 3 4 import time 5 6 localtime = time.asctime(time.localtime(time.time())) 7 print("本地时间为 :", localtime)
输出结果:
1 本地时间为 : Mon Nov 14 21:24:39 2016
格式化日期
可以使用 time 模块的 strftime 方法来格式化日期
time.strftime(format[, t])
1 #!/usr/bin/env python 2 # -*- coding: UTF-8 -*- 3 4 import time 5 6 # 格式化成2016-03-20 11:45:39形式 7 print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) 8 9 # 格式化成Sat Mar 28 22:24:24 2016形式 10 print(time.strftime("%a %b %d %H:%M:%S %Y", time.localtime())) 11 12 # 将格式字符串转换为时间戳 13 a = "Mon Nov 14 21:31:45 2016" 14 print(time.mktime(time.strptime(a, "%a %b %d %H:%M:%S %Y")))
输出结果:
2016-11-14 21:32:21
Mon Nov 14 21:32:21 2016
1479130305.0
python中时间日期格式化符号:
- %y 两位数的年份表示(00-99)
- %Y 四位数的年份表示(000-9999)
- %m 月份(01-12)
- %d 月内中的一天(0-31)
- %H 24小时制小时数(0-23)
- %I 12小时制小时数(01-12)
- %M 分钟数(00=59)
- %S 秒(00-59)
- %a 本地简化星期名称
- %A 本地完整星期名称
- %b 本地简化的月份名称
- %B 本地完整的月份名称
- %c 本地相应的日期表示和时间表示
- %j 年内的一天(001-366)
- %p 本地A.M.或P.M.的等价符
- %U 一年中的星期数(00-53)星期天为星期的开始
- %w 星期(0-6),星期天为星期的开始
- %W 一年中的星期数(00-53)星期一为星期的开始
- %x 本地相应的日期表示
- %X 本地相应的时间表示
- %Z 当前时区的名称
- %% %号本身
获取某月日历
Calendar模块有很广泛的方法用来处理年历和月历,例如打印某月的月历:
1 #!/usr/bin/env python 2 # -*- coding: UTF-8 -*- 3 4 import calendar 5 6 cal = calendar.month(2016, 11) 7 print("以下输出2016年11月份的日历:") 8 print(cal)
输出结果:
1 以下输出2016年11月份的日历: 2 November 2016 3 Mo Tu We Th Fr Sa Su 4 1 2 3 4 5 6 5 7 8 9 10 11 12 13 6 14 15 16 17 18 19 20 7 21 22 23 24 25 26 27 8 28 29 30
time 模块
time 模块包含以下内置函数
- time.altzone 返回格林威治西部的夏令时地区的偏移秒数(与UTC的时间差)。如果该地区在格林威治东部会返回负值(如西欧,包括英国)。对夏令时启用地区才能使用
1 >>> time.altzone 2 -32400
- time.asctime([tupletime]) 接受时间元组并返回一个可读的形式为 'Mon Nov 14 21:45:06 2016' 的24个字符的字符串
1 >>> time.asctime(time.localtime()) 2 'Mon Nov 14 21:45:06 2016'
- time.clock() 用以浮点数计算的秒数返回当前的CPU时间。用来衡量不同程序的耗时,比time.time()更有用
1 >>> time.clock() 2 2.83648743983101e-06
- time.ctime([secs]) 作用相当于asctime(localtime(secs)),未给参数相当于asctime()
1 >>> time.ctime() 2 'Mon Nov 14 21:48:23 2016'
- time.gmtime([secs]) 接收时间辍(1970纪元后经过的浮点秒数)并返回格林威治天文时间下的时间元组t。注:t.tm_isdst 始终为0
1 >>> time.gmtime() 2 time.struct_time(tm_year=2016, tm_mon=11, tm_mday=14, tm_hour=13, tm_min=49, tm_sec=3, tm_wday=0, tm_yday=319, tm_isdst=0)
- time.localtime([secs]) 接收时间辍(1970纪元后经过的浮点秒数)并返回当地时间下的时间元组t(t.tm_isdst可取0或1,取决于当地当时是不是夏令时)
1 >>> time.localtime() 2 time.struct_time(tm_year=2016, tm_mon=11, tm_mday=14, tm_hour=21, tm_min=50, tm_sec=10, tm_wday=0, tm_yday=319, tm_isdst=0)
- time.mktime(tupletime) 接受时间元组并返回时间辍(1970纪元后经过的浮点秒数)
1 >>> time.mktime(time.localtime()) 2 1479131695.0
- time.sleep(secs) 推迟调用线程的运行,secs指秒数
1 >>> print("Start : %s" % time.ctime()) 2 Start : Mon Nov 14 21:59:15 2016 3 >>> time.sleep(5) 4 >>> print("End : %s" % time.ctime()) 5 End : Mon Nov 14 21:59:20 2016
- time.strftime(fmt[,tupletime]) 接收以时间元组,并返回以可读字符串表示的当地时间,格式由fmt决定
1 >>> time.strftime("%b %d %Y %H:%M:%S", time.gmtime()) 2 'Nov 14 2016 14:01:42'
- time.strptime(str,fmt='%a %b %d %H:%M:%S %Y') 根据fmt的格式把一个时间字符串解析为时间元组
1 >>> struct_time = time.strptime("30 Nov 16", "%d %b %y") 2 >>> print(struct_time) 3 time.struct_time(tm_year=2016, tm_mon=11, tm_mday=30, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=335, tm_isdst=-1)
- time.time( ) 返回当前时间的时间戳(1970纪元后经过的浮点秒数)
1 >>> time.time() 2 1479132293.9487014
时间转换
日历(Calendar)模块
此模块的函数都是日历相关的,例如打印某月的字符月历。
星期一是默认的每周第一天,星期天是默认的最后一天。
更改设置需调用 calendar.setfirstweekday() 函数。
模块包含了以下内置函数:
- calendar.calendar(year,w=2,l=1,c=6) 返回一个多行字符串格式的year年年历,3个月一行,间隔距离为c,每日宽度间隔为w字符,每行长度为21* W+18+2* C,l是每星期行数
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import calendar 5 6 print(calendar.calendar(2016, w=2, l=1, c=6))
输出结果:
1 2016 2 3 January February March 4 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 5 1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 6 6 4 5 6 7 8 9 10 8 9 10 11 12 13 14 7 8 9 10 11 12 13 7 11 12 13 14 15 16 17 15 16 17 18 19 20 21 14 15 16 17 18 19 20 8 18 19 20 21 22 23 24 22 23 24 25 26 27 28 21 22 23 24 25 26 27 9 25 26 27 28 29 30 31 29 28 29 30 31 10 11 April May June 12 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 13 1 2 3 1 1 2 3 4 5 14 4 5 6 7 8 9 10 2 3 4 5 6 7 8 6 7 8 9 10 11 12 15 11 12 13 14 15 16 17 9 10 11 12 13 14 15 13 14 15 16 17 18 19 16 18 19 20 21 22 23 24 16 17 18 19 20 21 22 20 21 22 23 24 25 26 17 25 26 27 28 29 30 23 24 25 26 27 28 29 27 28 29 30 18 30 31 19 20 July August September 21 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 22 1 2 3 1 2 3 4 5 6 7 1 2 3 4 23 4 5 6 7 8 9 10 8 9 10 11 12 13 14 5 6 7 8 9 10 11 24 11 12 13 14 15 16 17 15 16 17 18 19 20 21 12 13 14 15 16 17 18 25 18 19 20 21 22 23 24 22 23 24 25 26 27 28 19 20 21 22 23 24 25 26 25 26 27 28 29 30 31 29 30 31 26 27 28 29 30 27 28 October November December 29 Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 30 1 2 1 2 3 4 5 6 1 2 3 4 31 3 4 5 6 7 8 9 7 8 9 10 11 12 13 5 6 7 8 9 10 11 32 10 11 12 13 14 15 16 14 15 16 17 18 19 20 12 13 14 15 16 17 18 33 17 18 19 20 21 22 23 21 22 23 24 25 26 27 19 20 21 22 23 24 25 34 24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31 35 31
- calendar.firstweekday() 返回当前每周起始日期的设置。默认情况下,首次载入 calendar 模块时返回0,即星期一。
1 >>> calendar.firstweekday() 2 0
- calendar.isleap(year) 是闰年返回True,否则为false。
1 >>> calendar.isleap(2016) 2 True
- calendar.leapdays(y1,y2) 返回在Y1,Y2两年之间的闰年总数。
1 >>> calendar.leapdays(2000, 2016) 2 4
- calendar.month(year,month,w=2,l=1) 返回一个多行字符串格式的 year 年 month 月日历,两行标题,一周一行,每日宽度间隔为 w 字符,每行的长度为7* w+6,l是每星期的行数
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import calendar 5 6 print(calendar.month(2016, 11, w=2, l=1))
输出结果:
1 November 2016 2 Mo Tu We Th Fr Sa Su 3 1 2 3 4 5 6 4 7 8 9 10 11 12 13 5 14 15 16 17 18 19 20 6 21 22 23 24 25 26 27 7 28 29 30
- calendar.monthcalendar(year, month) 返回一个整数的单层嵌套列表。每个子列表装载代表一个星期的整数,Year 年month 月外的日期都设为0,范围内的日子都由该月第几日表示,从1开始
>>> calendar.monthcalendar(2016, 11)
[[0, 1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12, 13], [14, 15, 16, 17, 18, 19, 20], [21, 22, 23, 24, 25, 26, 27], [28, 29, 30, 0, 0, 0, 0]]
- calendar.monthrange(year,month) 返回两个整数。第一个是该月的星期几的日期码,第二个是该月的日期码,日从0(星期一)到6(星期日),月从1到12
1 >>> calendar.monthrange(2016, 11) 2 (1, 30)
- calendar.prcal(year,w=2,l=1,c=6) 相当于 print(calendar.calendar(year,w,l,c))
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import calendar 5 6 print(calendar.prcal(2016, w=2, l=1, c=6))
输出结果:
2016 January February March Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 6 4 5 6 7 8 9 10 8 9 10 11 12 13 14 7 8 9 10 11 12 13 11 12 13 14 15 16 17 15 16 17 18 19 20 21 14 15 16 17 18 19 20 18 19 20 21 22 23 24 22 23 24 25 26 27 28 21 22 23 24 25 26 27 25 26 27 28 29 30 31 29 28 29 30 31 April May June Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 1 2 3 1 1 2 3 4 5 4 5 6 7 8 9 10 2 3 4 5 6 7 8 6 7 8 9 10 11 12 11 12 13 14 15 16 17 9 10 11 12 13 14 15 13 14 15 16 17 18 19 18 19 20 21 22 23 24 16 17 18 19 20 21 22 20 21 22 23 24 25 26 25 26 27 28 29 30 23 24 25 26 27 28 29 27 28 29 30 30 31 July August September Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 1 2 3 1 2 3 4 5 6 7 1 2 3 4 4 5 6 7 8 9 10 8 9 10 11 12 13 14 5 6 7 8 9 10 11 11 12 13 14 15 16 17 15 16 17 18 19 20 21 12 13 14 15 16 17 18 18 19 20 21 22 23 24 22 23 24 25 26 27 28 19 20 21 22 23 24 25 25 26 27 28 29 30 31 29 30 31 26 27 28 29 30 October November December Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 1 2 1 2 3 4 5 6 1 2 3 4 3 4 5 6 7 8 9 7 8 9 10 11 12 13 5 6 7 8 9 10 11 10 11 12 13 14 15 16 14 15 16 17 18 19 20 12 13 14 15 16 17 18 17 18 19 20 21 22 23 21 22 23 24 25 26 27 19 20 21 22 23 24 25 24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31 31 None
- calendar.prmonth(year,month,w=2,l=1) 相当于 print(calendar.calendar(year,w,l,c))
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import calendar 5 6 calendar.prmonth(2016, 11, w=2, l=1)
输出结果:
1 November 2016 2 Mo Tu We Th Fr Sa Su 3 1 2 3 4 5 6 4 7 8 9 10 11 12 13 5 14 15 16 17 18 19 20 6 21 22 23 24 25 26 27 7 28 29 30
- calendar.setfirstweekday(weekday) 设置每周的起始日期码。0(星期一)到6(星期日)
1 >>> calendar.setfirstweekday(2) 2 >>> calendar.firstweekday( ) 3 2
- calendar.timegm(tupletime) 和 time.gmtime 相反:接受一个时间元组形式,返回该时刻的时间辍(1970纪元后经过的浮点秒数)
1 >>> calendar.timegm(time.localtime()) 2 1479164045
- calendar.weekday(year,month,day) 返回给定日期的日期码。0(星期一)到6(星期日)。月份为 1(一月) 到 12(12月)
1 >>> calendar.weekday(2016,11,14) 2 0
datetime 模块
- datetime.datetime.now() 返回当前时间
1 >>> print(datetime.datetime.now()) 2 2016-11-14 23:02:30.931429
- datetime.date.fromtimestamp(time.time()) 时间戳直接转成日期格式
1 >>> print(datetime.date.fromtimestamp(time.time())) 2 2016-11-14
- datetime.datetime.now() + datetime.timedelta(3)) 当前时间+3天
- datetime.datetime.now() + datetime.timedelta(-3)) 当前时间-3天
- datetime.datetime.now() + datetime.timedelta(hours=3)) 当前时间+3小时
- datetime.datetime.now() + datetime.timedelta(minutes=30) 当前时间+30分
1 >>> print(datetime.datetime.now()) 2 2016-11-14 23:05:03.731169 3 >>> print(datetime.datetime.now() + datetime.timedelta(3)) # 当前时间+3天 4 2016-11-17 23:05:03.743169 5 >>> print(datetime.datetime.now() + datetime.timedelta(-3)) # 当前时间-3天 6 2016-11-11 23:05:03.755170 7 >>> print(datetime.datetime.now() + datetime.timedelta(hours=3)) # 当前时间+3小时 8 2016-11-15 02:05:03.765171 9 >>> print(datetime.datetime.now() + datetime.timedelta(minutes=30)) # 当前时间+30分 10 2016-11-14 23:35:04.858233
- replace(minute, hour) 时间替换
1 >>> c_time = datetime.datetime.now() 2 >>> print(c_time) 3 2016-11-14 23:07:37.762979 4 >>> print(c_time.replace(minute=3, hour=2)) 5 2016-11-14 02:03:37.762979
2)random
Python中的random模块用于生成随机数
random.random()
用于生成一个0到1的随机浮点数: 0 <= n < 1.0
1 >>> import random 2 >>> random.random() 3 0.99107532292498801
random.uniform(a, b)
用于生成一个指定范围内的随机浮点数,两个参数其中一个是上限,一个是下限。如果a > b,则生成的随机数n: a <= n <= b;如果 a <b, 则 b <= n <= a。
1 >>> import random 2 >>> random.uniform(10, 20) 3 12.893035403821591 4 >>> random.uniform(20, 10) 5 15.344944314032574
random.randint(a, b)
用于生成一个指定范围内的整数。其中参数a是下限,参数b是上限,生成的随机数n: a <= n <= b
1 >>> import random 2 >>> random.randint(12, 20) # 生成的随机数n: 12 <= n <= 20 3 16 4 >>> random.randint(20, 20) # 结果永远是20 5 20 6 >>> random.randint(20, 10) # 该语句是错误的,下限必须小于上限 7 Traceback (most recent call last): 8 File "<stdin>", line 1, in <module> 9 File "/usr/lib64/python2.6/random.py", line 228, in randint 10 return self.randrange(a, b+1) 11 File "/usr/lib64/python2.6/random.py", line 204, in randrange 12 raise ValueError, "empty range for randrange() (%d,%d, %d)" % (istart, istop, width) 13 ValueError: empty range for randrange() (20,11, -9)
random.randrange([start], stop[, step])
从指定范围内,按指定基数递增的集合中获取一个随机数。
1 >>> import random 2 >>> random.randrange(10, 100, 2) 3 80
结果相当于从 [10, 12, 14, 16, ... 96, 98] 序列中获取一个随机数。
random.randrange(10, 100, 2)在结果上与 random.choice(range(10, 100, 2) 等效。
random.choice(sequence)
从序列中获取一个随机元素,参数 sequence 表示一个有序类型。这里要说明 一下:sequence 在python 不是一种特定的类型,而是泛指一系列的类型。list, tuple, 字符串都属于sequence。
1 >>> import random 2 >>> random.choice("学习Python") 3 '\xe4' 4 >>> random.choice(["JGood", "is", "a", "handsome", "boy"]) 5 'boy' 6 >>> random.choice(("Tuple", "List", "Dict")) 7 'List'
random.shuffle(x[, random])
用于将一个列表中的元素打乱
1 >>> import random 2 >>> p = ["Python", "is", "powerful", "simple", "and so on..."] 3 >>> random.shuffle(p) 4 >>> p 5 ['is', 'Python', 'and so on...', 'powerful', 'simple']
random.sample(sequence, k)
从指定序列中随机获取指定长度的片,sample函数不会修改原有序列
1 >>> import random 2 >>> list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 3 >>> slice = random.sample(list, 5) 4 >>> slice 5 [8, 6, 9, 3, 7] 6 >>> list 7 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
多个字符中选取特定数量的字符
1 >>> import random 2 >>> random.sample('abcdefghij',3) 3 ['i', 'c', 'b']
random.sample 验证码应用
方式一:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import random 5 import string 6 7 str_source = string.ascii_letters + string.digits 8 code = random.sample(str_source, 6) 9 for i in code: 10 print(i, end="")
输出结果:
1 0sHxSZ
方式二:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import random 5 6 check_code = "" 7 for i in range(6): 8 current = random.randrange(0, 6) 9 if current != i: 10 temp = chr(random.randint(65, 90)) 11 else: 12 temp = random.randint(0, 9) 13 check_code += str(temp) 14 print(check_code)
输出结果:
1 HY5YNN
3)os
os.name
输出字符串指示正在使用的平台。
如果是window 则用'nt'表示:
1 >>> import os 2 >>> os.name 3 'nt'
对于Linux/Unix用户,它是'posix':
1 >>> import os 2 >>> os.name 3 'posix'
os.getcwd()
获取当前工作目录,即当前 python 脚本工作的目录路径
1 >>> import os 2 >>> os.getcwd() 3 '/home/test'
os.chdir("dirname")
改变当前脚本工作目录,相当于shell下cd
1 >>> import os 2 >>> os.getcwd() 3 '/home/test' 4 >>> os.chdir("Python35") 5 >>> os.getcwd() 6 '/usr/local/python35'
os.curdir
返回当前目录: ('.')
1 >>> import os 2 >>> os.curdir 3 '.'
os.pardir
获取当前目录的父目录字符串名:('..')
1 >>> import os 2 >>> os.pardir 3 '..'
os.makedirs('dirname1/dirname2')
可生成多层递归目录
1 >>> import os 2 >>> os.getcwd() 3 '/home/test' 4 >>> os.makedirs('test1/test2') 5 >>> os.chdir('test1') 6 >>> os.getcwd() 7 '/home/test/test1' 8 >>> os.chdir('test2') 9 >>> os.getcwd() 10 '/home/test/test1/test2'
os.removedirs('dirname1')
若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
1 >>> import os 2 >>> os.getcwd() 3 '/home/test/test1/test2' 4 >>> os.chdir('..') 5 >>> os.getcwd() 6 '/home/test/test1' 7 >>> os.removedirs('test2') 8 >>> os.getcwd() 9 '/home/test/test1' 10 >>> os.chdir('test2') 11 Traceback (most recent call last): 12 File "<stdin>", line 1, in <module> 13 OSError: [Errno 2] No such file or directory: 'test2'
os.mkdir('dirname')
生成单级目录,相当于 shell 中 mkdir dirname
1 >>> import os 2 >>> os.getcwd() 3 '/home/test' 4 >>> os.chdir('test1') 5 >>> os.getcwd() 6 '/home/test/test1' 7 >>> os.listdir('.') 8 [] 9 >>> os.mkdir('test2') 10 >>> os.listdir('.') 11 ['test2']
os.listdir('dirname')
列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
1 >>> import os 2 >>> os.listdir('.') 3 ['.zshrc', '.subversion', '.dbshell', '.mozilla', '.bash_logout', '.gnome2', '.bash_history', '.bashrc', 'test1', '.viminfo', '.emacs', '.bash_profile']
os.rmdir('dirname')
删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
1 >>> import os 2 >>> os.getcwd() 3 '/home/test/test1' 4 >>> os.listdir('.') 5 ['test2'] 6 >>> os.rmdir('test2') 7 >>> os.listdir('.') 8 []
os.remove()
删除一个文件
1 >>> import os 2 >>> os.listdir('.') 3 ['test.log'] 4 >>> os.remove('test.log') 5 >>> os.listdir('.') 6 []
os.rename("oldname","newname")
重命名文件/目录
1 >>> import os 2 >>> os.listdir('.') 3 ['test.log'] 4 >>> os.rename('test.log','hello.txt') 5 >>> os.listdir('.') 6 ['hello.txt']
os.stat('path/filename')
获取文件/目录信息
1 >>> import os 2 >>> os.listdir('.') 3 ['hello.txt'] 4 >>> os.stat('hello.txt') 5 posix.stat_result(st_mode=33188, st_ino=2629852, st_dev=64768L, st_nlink=1, st_uid=505, st_gid=301, st_size=0, st_atime=1478588652, st_mtime=1478588652, st_ctime=1478588686)
os.sep
输出操作系统特定的路径分隔符
win下为"\\"
1 >>> import os 2 >>> os.sep 3 '\\'
Linux下为"/"
>>> import os >>> os.sep '/'
os.linesep
输出当前平台使用的行终止符
win下为"\r\n"
1 >>> import os 2 >>> os.linesep 3 '\r\n'
Linux下为"\n"
1 >>> import os 2 >>> os.linesep 3 '\n'
os.pathsep
输出用于分割文件路径的字符串
win下为';'
1 >>> import os 2 >>> os.pathsep 3 ';'
Linux下为':'
1 >>> import os 2 >>> os.pathsep 3 ':'
os.system("bash command")
运行shell命令,直接显示
1 >>> import os 2 >>> os.system('date') 3 Tue Nov 8 15:15:26 CST 2016 4 0
os.environ
获取系统环境变量
1 >>> import os 2 >>> os.environ 3 environ({'OS': 'Windows_NT', 'PROCESSOR_REVISION': '1706', 'HOMEPATH': '\\Users\\test', 'APPDATA': 'C:\\Users\\test\\AppData\\Roaming', 'PUBLIC': 'C:\\Users\\Public', 'PROGRAMFILES(X86)': 'C:\\Program Files (x86)', 'COMPUTERNAME': 'TEST-PC', 'SYSTEMDRIVE': 'C:', 'LOCALAPPDATA': 'C:\\Users\\test\\AppData\\Local', 'COMMONPROGRAMFILES': 'C:\\Program Files\\Common Files', 'SESSIONNAME': 'Console', 'FP_NO_HOST_CHECK': 'NO', 'PROCESSOR_IDENTIFIER': 'Intel64 Family 6 Model 23 Stepping 6, GenuineIntel', 'PROGRAMDATA': 'C:\\ProgramData', 'USERNAME': 'test','PROGRAMFILES': 'C:\\Program Files', 'CATALINA_HOME': 'D:\\apache-tomcat-6.0.45', 'NUMBER_OF_PROCESSORS': '2', 'TMP': 'C:\\Users\\test\\AppData\\Local\\Temp','PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW', 'PROMPT': '$P$G', 'COMMONPROGRAMFILES(X86)': 'C:\\Program Files (x86)\\Common Files', 'COMSPEC': 'C:\\Windows\\system32\\cmd.exe', 'PROGRAMW6432': 'C:\\Program Files', 'SYSTEMROOT': 'C:\\Windows', 'PATH': 'D:\\Python35\\Scripts\\;D:\\Python35\\;D:\\oracle\\product\\10.2.0\\client_1\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;D:\\Program Files\\TortoiseSVN\\bin;C:\\Redis\\;C:\\Java\\jdk1.6\\bin;D:\\MongoDB\\Server\\3.2\\bin', 'TEMP': 'C:\\Users\\test\\AppData\\Local\\Temp', 'USERDOMAIN': 'test-PC', 'COMMONPROGRAMW6432': 'C:\\Program Files\\Common Files', 'PROCESSOR_LEVEL': '6', 'PSMODULEPATH': 'C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules\\;C:\\Program Files\\Intel\\', 'USERPROFILE': 'C:\\Users\\test', 'ALLUSERSPROFILE': 'C:\\ProgramData', 'LOGONSERVER': '\\\\TEST-PC', 'WINDIR': 'C:\\Windows', 'JAVA_HOME': 'C:\\Java\\jdk1.6', 'HOMEDRIVE': 'C:', 'PROCESSOR_ARCHITECTURE': 'AMD64'})
os.path.abspath(path)
返回path规范化的绝对路径
1 >>> import os 2 >>> os.path.abspath('test1') 3 '/home/test/test1/test1'
os.path.split(path)
将path分割成目录和文件名二元组返回
1 >>> import os 2 >>> os.path.split('/home/test') 3 ('/home', 'test')
os.path.dirname(path)
返回 path 的目录,其实就是os.path.split(path)的第一个元素
1 >>> import os 2 >>> os.path.dirname('/home/test') 3 '/home'
os.path.basename(path)
返回path最后的文件名,如果 path 以 / 或 \ 结尾,那么就会返回空值,即os.path.split(path)的第二个元素
1 >>> import os 2 >>> os.path.basename('home/test') 3 'test' 4 >>> os.path.basename('home/test/') 5 ''
os.path.exists(path)
如果path存在,返回True;如果path不存在,返回False
1 >>> import os 2 >>> os.getcwd() 3 '/home/test/test1' 4 >>> os.listdir('.') 5 ['test2', 'hello.txt'] 6 >>> os.path.exists('test1') 7 False 8 >>> os.path.exists('test2') 9 True
os.path.isabs(path)
如果path是绝对路径,返回True
1 >>> import os 2 >>> os.path.isabs('/home/test/test1') 3 True 4 >>> os.path.isabs('test1') 5 False
os.path.isfile(path)
如果path是一个存在的文件,返回True。否则返回False
1 >>> import os 2 >>> os.listdir('.') 3 ['test2', 'hello.txt'] 4 >>> os.path.isfile('hello.txt') 5 True 6 >>> os.path.isfile('test.log') 7 False
os.path.isdir(path)
如果path是一个存在的目录,则返回True。否则返回False
1 >>> import os 2 >>> os.listdir('.') 3 ['test2', 'hello.txt'] 4 >>> os.path.isdir('test2') 5 True 6 >>> os.path.isdir('hello.txt') 7 False
os.path.join(path1[, path2[, ...]])
将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
1 >>> import os 2 >>> os.path.join('test1','test2','test') 3 'test1/test2/test' 4 >>> os.path.join('/home/test/test1','test2','test') 5 '/home/test/test1/test2/test' 6 >>> os.path.join('test1','/home/test/test1/test2','test') 7 '/home/test/test1/test2/test'
os.path.getatime(path)
返回path所指向的文件或者目录的最后存取时间
1 >>> import os 2 >>> os.listdir('.') 3 ['test2', 'hello.txt'] 4 >>> os.path.getatime('hello.txt') 5 1478588652.6452732
os.path.getmtime(path)
返回path所指向的文件或者目录的最后修改时间
1 >>> import os 2 >>> os.listdir('.') 3 ['test2', 'hello.txt'] 4 >>> os.path.getmtime('hello.txt') 5 1478588652.6452732
os.path.split(path)
返回一个路径的目录名和文件名
1 >>> import os 2 >>> os.path.split('/home/test/test1/hello.txt') 3 ('/home/test/test1', 'hello.txt')
os.path.getsize(name)
获得文件大小
1 >>> import os 2 >>> os.listdir('.') 3 ['test2', 'hello.txt'] 4 >>> os.path.getsize('hello.txt') 5 12 6 >>> os.path.getsize('test2') 7 4096
4)sys
sys.argv
在外部向程序内部传递参数,以list的形式返回参数列表
1 >>> import sys 2 >>> sys.argv 3 ['']
示例:
1 #!/usr/bin/env python 2 # -*- coding:UTF-8 -*- 3 4 import sys 5 6 print(sys.argv[0]) 7 print(sys.argv[1])
运行结果:
1 $ python sys.py argv1 2 sys.py 3 argv1
sys.exit(n)
执行到主程序末尾,解释器自动退出,但是如果需要中途退出程序,可以调用sys.exit函数,带有一个可选的整数参数返回给调用它的程序,表示你可以在主程序中捕获对sys.exit的调用。(0是正常退出,其他为异常)
1 >>> import sys 2 >>> sys.exit(1) 3 [root@test ~]$ echo $? 4 1
sys.version
获取Python解释程序的版本信息
1 >>> import sys 2 >>> sys.version 3 '3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)]'
sys.maxint
获取最大的int值
1 >>> import sys 2 >>> sys.maxint 3 9223372036854775807
sys.path
返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
>>> import sys >>> sys.path ['', '/usr/local/python35/lib/python35.zip', '/usr/local/python35/lib/python3.5', '/usr/local/python35/lib/python3.5/plat-linux', '/usr/local/python35/lib/python3.5/lib-dynload', '/usr/local/python35/lib/python3.5/site-packages']
sys.platform
返回操作系统平台名称
1 >>> import sys 2 >>> sys.platform 3 'linux'
sys.modules
是一个全局字典,该字典是python启动后就加载在内存中。每当程序员导入新的模块,
sys.modules
将自动记录该模块。当第二次再导入该模块时,python会直接到字典中查找,从而加快了程序运行的速度。它拥有字典所拥有的一切方法。
1 >>> import sys 2 >>> sys.modules 3 {'_sitebuiltins': <module '_sitebuiltins' from '/usr/local/python35/lib/python3.5/_sitebuiltins.py'>, 'encodings.aliases': <module 'encodings.aliases' from '/usr/local/python35/lib/python3.5/encodings/aliases.py'>, 'errno': <module 'errno' (built-in)>, '_collections_abc': <module '_collections_abc' from '/usr/local/python35/lib/python3.5/_collections_abc.py'>, 'atexit': <module 'atexit' (built-in)>, 'posixpath': <module 'posixpath' from '/usr/local/python35/lib/python3.5/posixpath.py'>, '_codecs': <module '_codecs' (built-in)>, '__main__': <module '__main__' (built-in)>, 'builtins': <module 'builtins' (built-in)>, 'io': <module 'io' from '/usr/local/python35/lib/python3.5/io.py'>, 'genericpath': <module 'genericpath' from '/usr/local/python35/lib/python3.5/genericpath.py'>, 'site': <module 'site' from '/usr/local/python35/lib/python3.5/site.py'>, '_io': <module 'io' (built-in)>, '_frozen_importlib_external': <module '_frozen_importlib_external' (frozen)>, '_stat': <module '_stat' (built-in)>, '_thread': <module '_thread' (built-in)>, 'encodings.latin_1': <module 'encodings.latin_1' from '/usr/local/python35/lib/python3.5/encodings/latin_1.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from '/usr/local/python35/lib/python3.5/encodings/utf_8.py'>, '_imp': <module '_imp' (built-in)>, 'os': <module 'os' from '/usr/local/python35/lib/python3.5/os.py'>, '_weakref': <module '_weakref' (built-in)>, 'zipimport': <module 'zipimport' (built-in)>, 'posix': <module 'posix' (built-in)>, 'stat': <module 'stat' from '/usr/local/python35/lib/python3.5/stat.py'>, 'os.path': <module 'posixpath' from '/usr/local/python35/lib/python3.5/posixpath.py'>, 'codecs': <module 'codecs' from '/usr/local/python35/lib/python3.5/codecs.py'>, 'abc': <module 'abc' from '/usr/local/python35/lib/python3.5/abc.py'>, '_frozen_importlib': <module '_frozen_importlib' (frozen)>, 'encodings': <module 'encodings' from '/usr/local/python35/lib/python3.5/encodings/__init__.py'>, 'marshal': <module 'marshal' (built-in)>, '_signal': <module '_signal' (built-in)>, '_weakrefset': <module '_weakrefset' from '/usr/local/python35/lib/python3.5/_weakrefset.py'>, 'sys': <module 'sys' (built-in)>, 'sysconfig': <module 'sysconfig' from '/usr/local/python35/lib/python3.5/sysconfig.py'>, '_warnings': <module '_warnings' (built-in)>, '_sysconfigdata': <module '_sysconfigdata' from '/usr/local/python35/lib/python3.5/_sysconfigdata.py'>}
sys.stdout.write(
'please:'
)
1 >>> import sys 2 >>> sys.stdout.write('please:') 3 please:7
val
=
sys.stdin.readline()[:
-
1
]
1 >>> import sys 2 >>> val = sys.stdin.readline()[:-1] 3 Hello World 4 >>> val 5 'Hello World'
5)shutil
高级的对文件、文件夹、压缩包处理的模块
copyfile( src, dst) | 从源src复制到dst中去。当然前提是目标地址是具备可写权限。抛出的异常信息为IOException. 如果当前的dst已存在的话就会被覆盖掉 |
copymode( src, dst) | 只是会复制其权限其他的东西是不会被复制的 |
copystat( src, dst) | 复制权限、最后访问时间、最后修改时间 |
copy( src, dst) | 复制一个文件到一个文件或一个目录 |
copy2( src, dst) | 在copy上的基础上再复制文件最后访问时间与修改时间也复制过来了,类似于cp –p的东西 |
copy2( src, dst) | 如果两个位置的文件系统是一样的话相当于是rename操作,只是改名;如果是不在相同的文件系统的话就是做move操作 |
copytree(olddir,newdir,True/Flase) | 把olddir拷贝一份newdir,如果第3个参数是True,则复制目录时将保持文件夹下的符号连接,如果第3个参数是False,则将在复制的目录下生成物理副本来替代符号连接 |
shutil.copyfileobj(fsrc, fdst[, length])
将文件内容拷贝到另一个文件中,可以部分内容
shutil.copyfile(src, dst)
拷贝文件
shutil.copymode(src, dst)
仅拷贝权限。内容、组、用户均不变
shutil.copystat(src, dst)
拷贝状态的信息,包括:mode bits, atime, mtime, flags
shutil.copy(src, dst)
拷贝文件和权限
shutil.copy2(src, dst)
拷贝文件和状态信息
shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
递归的去拷贝文件
例如:copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))
shutil.rmtree(path[, ignore_errors[, onerror]])
递归的去删除文件
shutil.move(src, dst)
递归的去移动文件
shutil.make_archive(base_name, format,...)
创建压缩包并返回文件路径,例如:zip、tar
- base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如:www =>保存至当前路径
如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/ - format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
- root_dir: 要压缩的文件夹路径(默认当前目录)
- owner: 用户,默认当前用户
- group: 组,默认当前组
- logger: 用于记录日志,通常是logging.Logger对象
1
2
3
4
5
6
7
8
9
|
#将 /Users/wupeiqi/Downloads/test 下的文件打包放置当前程序目录
import
shutil
ret
=
shutil.make_archive(
"wwwwwwwwww"
,
'gztar'
, root_dir
=
'/Users/wupeiqi/Downloads/test'
)
#将 /Users/wupeiqi/Downloads/test 下的文件打包放置 /Users/wupeiqi/目录
import
shutil
ret
=
shutil.make_archive(
"/Users/wupeiqi/wwwwwwwwww"
,
'gztar'
, root_dir
=
'/Users/wupeiqi/Downloads/test'
)
|
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:
6)json & pickle
用于序列化的两个模块
- json,用于字符串和 python 数据类型间进行转换
- pickle,用于 python 特有的类型和 python 数据类型间进行转换
Json 模块提供了四个功能:dumps、dump、loads、load
pickle 模块提供了四个功能:dumps、dump、loads、load
JSON 模块
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成,它基于 JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999 的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。
Python3 中可以使用 json 模块来对 JSON 数据进行编解码,它包含了两个函数:
- json.dumps():对数据进行编码
- json.loads():对数据进行解码
json.dumps与json.loads实例
1 #!/usr/bin/env python 2 # -*- coding:UTF-8 -*- 3 4 import json 5 # 将python的基础数据类型转化成字符串 6 dic = {"k1": "v1", "k2": "v2"} 7 print("Python原始数据:", repr(dic), type(dic)) 8 result = json.dumps(dic) # 将字典类型转换为字符串类型 9 print("JSON对象:", result, type(result))
输出结果:
1 Python原始数据: {'k2': 'v2', 'k1': 'v1'} <class 'dict'> 2 JSON对象: {"k2": "v2", "k1": "v1"} <class 'str'>
JSON 编码的字符串转换回 Python 数据结构
1 #!/usr/bin/env python 2 # -*- coding:UTF-8 -*- 3 4 import json 5 # 将 python 的基础数据类型转化成字符串 6 dic = {"k1": "v1", "k2": "v2"} 7 print("Python原始数据:", repr(dic), type(dic)) 8 result = json.dumps(dic) # 将字典类型转换为字符串类型 9 print("JSON对象:", result, type(result)) 10 11 # 将 python 字符串类型转化为 python 基本数据类型 12 result = json.loads(result) 13 print("result['k1']:", result['k1']) 14 print("result['k2']:", result['k2'])
输出结果:
1 Python原始数据: {'k1': 'v1', 'k2': 'v2'} <class 'dict'> 2 JSON对象: {"k1": "v1", "k2": "v2"} <class 'str'> 3 result['k1']: v1 4 result['k2']: v2
如果要处理的是文件而不是字符串,可以使用 json.dump() 和 json.load() 来编码和解码JSON数据
1 #!/usr/bin/env python 2 # -*- coding:UTF-8 -*- 3 4 import json 5 6 data = { 7 'name': "James", 8 'age': 24, 9 'job': "IT" 10 } 11 # 写入 json 数据 12 with open('db.json', 'w', encoding="UTF-8") as f: 13 json.dump(data, f) 14 15 # 读取json数据 16 with open('db.json', 'r', encoding="UTF-8") as f: 17 res = json.load(f) 18 print(res,type(res))
输出结果:
1 {'name': 'James', 'age': 24, 'job': 'IT'} <class 'dict'>
PICKLE 模块
pickle 模块使用的数据格式是 python 专用的,并且不同版本不向后兼容,同时也不能被其他语言说识别。要和其他语言交互,可以使用内置的 json 包使用 pickle 模块你可以把Python对象直接保存到文件,而不需要把他们转化为字符串,也不用底层的文件访问操作把它们写入到一个二进制文件里。 pickle模块会创建一个python语言专用的二进制格式,基本上不用考虑任何文件细节,它会帮你干净利落地完成读写独享操作,唯一需要的只是一个合法的文件句柄。
python3中可以使用pickle模块,对数据进行编解码。它包含两个函数:
- pickle.dumps()
- pickle.loads()
pickle.dumps与pickle.loads实例
1 #!/usr/bin/env python 2 # -*- coding:UTF-8 -*- 3 4 import pickle 5 6 data = { 7 'name': "James", 8 'age': 24, 9 'job': "IT" 10 } 11 12 print("原始python对象:", repr(data)) 13 r = pickle.dumps(data) 14 print("pickle转换后的对象:", r) 15 res = pickle.loads(r) 16 print("res['name']:", res['name']) 17 print("res['age']:", res['age']) 18 print("res['job']:", res['job'])
输出结果:
1 原始python对象: {'name': 'James', 'job': 'IT', 'age': 24} 2 pickle转换后的对象: b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x05\x00\x00\x00Jamesq\x02X\x03\x00\x00\x00jobq\x03X\x02\x00\x00\x00ITq\x04X\x03\x00\x00\x00ageq\x05K\x18u.' 3 res['name']: James 4 res['age']: 24 5 res['job']: IT
如果要处理的是文件而不是字符串,你可以使用 pickle.dump() 和 pickle.load() 来编码和解码JSON数据
1 #!/usr/bin/env python 2 # -*- coding:UTF-8 -*- 3 4 import pickle 5 6 data = { 7 'name': "James", 8 'age': 24, 9 'job': "IT" 10 } 11 # 写入数据,要以wb格式写入 12 pickle.dump(data, open('db', 'wb')) 13 # 读取数据,要以rb格式读取 14 f = open('db', 'rb') 15 res = pickle.load(f) 16 print(res)
输出结果:
1 {'name': 'James', 'age': 24, 'job': 'IT'}
pickle和json的区别:
- json 适合跨语言,对于 python 而言仅适用于 Python 基本数据类型
- pickle 仅适用于 python,pickle 适用于 python 所有数据类型的序列化
- pickle 写入和读取文件时,用的是 ‘b’模式,而 json 没有。
- json 只能序列化最基本的数据类型,而 pickle 可以序列化所有的数据类型,包括类,函数都可以序列化。
7)shelve
8)xml 处理
9)yaml 处理
10)configparser
11) hashlib
12) subprocess
subprocess模块是子进程管理器,用户来生成子进程,并可以通过管道连接他们的输入、输出、错误,以及获取它们的返回值。
subprocess模块用来代替多个旧模块和函数,例如:
- os.system
- os.spawn*
- os.popen*
- popen2.*
- commands.*
subprocess.call
语法:
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
语义:
运行由args指定的命令,直到命令结束后,返回返回码的属性值。
上面的参数是最常见的方式,下面是示例代码:
>>>
>>> subprocess.call(["ls", "-l"])
0
>>> subprocess.call("exit 1", shell=True)
1
使用 shell=True 是一种安全保护机制。
在使用这个函数时,不要使用 stdout=PIPE 或 stderr=PIPE 参数,不然会导致子进程输出的死锁。
如果要使用管道,可以在 communicate()方法中使用Popen
示例代码:
import subprocess
rc = subprocess.call(["ls","-l"])
可以通过一个shell来解释一整个字符串:
import subprocess
out = subprocess.call("ls -l", shell=True)
out = subprocess.call("cd ..", shell=True)
使用了shell=True这个参数。
这个时候,我们使用一整个字符串,而不是一个表来运行子进程。
Python将先运行一个shell,再用这个shell来解释这整个字符串。
shell命令中有一些是shell的内建命令,这些命令必须通过shell运行,$cd。
shell=True允许我们运行这样一些命令。
2. subprocess.check_call
语法:
subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
语义:
运行由args指定的命令,直到命令执行完成。
如果返回码为零,则返回。否则,抛出 CalledProcessError异常。
CalledProcessError对象包含有返回码的属性值。
上面显示的参数仅仅是最常见的,下面是用户更常用的参数。
示例代码如下:
>>>
>>> subprocess.check_call(["ls", "-l"])
0
>>> subprocess.check_call("exit 1", shell=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
这个函数在python 2.5版本中引入。
WARNING: 使用 shell=True 是一种安全机制。
NOTE: 不要在这个函数中使用 stdout=PIPE 或 stderr=PIPE, 否则会造成子进程死锁。
如果需要使用管道,可以在 communicate()方法中使用Popen.
3. subprocess.check_output
语法:
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
语义:
运行args定义的命令,并返回一个字符串表示的输出值。
如果返回码为非零,则抛出 CalledProcessError异常。
示例代码:
>>>
>>> subprocess.check_output(["echo", "Hello World!"])
'Hello World!\n'
>>> subprocess.check_output("exit 1", shell=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
如果要捕捉结果中的标准错误,使用 stderr=subprocess.STDOUT参数:
>>>
>>> subprocess.check_output(
... "ls non_existent_file; exit 0",
... stderr=subprocess.STDOUT,
... shell=True)
'ls: non_existent_file: No such file or directory\n'
这个函数在python 2.7版本中引入。
WARNING: 使用 shell=True 是一种安全机制。
NOTE: 不要在这个函数中使用 stdout=PIPE 或 stderr=PIPE, 否则会造成子进程死锁。
如果需要使用管道,可以在 communicate()方法中使用Popen.
4. subprocess.PIPE
使用Popen时,用于 stdin, stdout和stderr参数的特殊值,表示打开连接标准流的管道。
5. subprocess.STDOUT
使用Popen时,用于 stderr 参数的特殊值,表示将标准错误重定向到标准输出的同一个句柄。
6. 异常 subprocess.CalledProcessError
当由 check_call()或 check_output()运行的进程返回非零状态值时抛出的异常。
7. returncode
子进程的退出状态。
8. cmd
子进程执行的命令。
9. output
如果check_output()抛出异常时,子进程的输出值。
否则,没有这个值。
1.1.1. 常用的参数
为了支持各种用户使用情况 ,Popen构建函数接收多种可选参数。
对于最典型的情况,许多参数都保留有安全的默认值,这些最常用的方式如下:
1. args
所有的函数都需要这个参数,并且它是一个字符串,或者是程序的参数序列。
提供一个参数序列是更推荐的方式,因为这样能允许模块接收空格 或 引号中的参数。
如果传递的是单个字符串,要么 shell=True, 或都要么 字符串就程序名字,并且不能带参数。
2. stdin, stdout 和 stderr
stdin, stdout和stderr指定了执行程序的标准输入,标准输出和标准错误的文件句柄。
它们的值可以是PIPE, 一个存在的文件描述符(正整数),一个存在的文件对象,或 None.
PIPE 表示创建一个连接子进程的新管道。
默认值 为 None, 表示不做重定向。
子进程的文件句柄可以从父进程中继承得到。
另外,stderr可以设置值为 STDOUT,表示子进程的错误数据可以和标准输出是同一个文件句柄。
当stdout 或 stderr的值为管道 并且 universal_newlines的值为真时,
对于以 ‘U'模式参数打开的新行,所有行的结束都会转换成'\n'。
3. shell
如果 shell的值为 True, 则指定的命令行会通过shell来执行。
如果你使用Python来作为流程控制,那这样的设置会很有用,因为它提供了绝大多数的系统shell命令且可以很方便地使用
shell的各种功能,如 shell 管道,文件名通配符,环境变量扩展,以及用户目录扩展符 ~。
但是,需要注意的是,Python 提供了类似shell功能的实现。
WARNING: 执行不受信任来源的shell命令会是一个严重的安全问题。
基于这一点,shell=True 是不建议的。
示例代码如下:
>>>
>>> from subprocess import call
>>> filename = input("What file would you like to display?\n")
What file would you like to display?
non_existent; rm -rf / #
>>> call("cat " + filename, shell=True) # Uh-oh. This will end badly...
shell=False 关闭了shell的所有基本功能 ,从而不会有上面所说的安全漏洞。
可以在Popen构建函数的帮助文档中看到,它只有在 shell=False时才能工作。
当使用 shell=True时,pipes.quote()可以被用于转译空格,shell的字符等。
1.1.2. Popen构建函数
subprocess中更底层的进程创建和管理可以通过Popen类实现。
它提供了更多的灵活性,程序员通过它能处理更多复杂的情况。
语法:
class subprocess.Popen(args, bufsize=0, executable=None,
stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None,
universal_newlines=False, startupinfo=None, creationflags=0)
语义:
在新进程中执行一个子程序。
在Unix中,这个类使用 类似于 os.execvp()方式来执行子程序。
在Windows中,这个类使用Windows的 CreateProcess()函数来执行子程序。
参数解析:
args: 一个程序参数序列,或者单个字符串。
默认的,要执行的程序应该是序列的第一个字段。
如果单个字符串,它的解析依赖于平台
在Unix中,如果 args是一个字符串,那么这个字符串解释成被执行程序的名字或路径。
然而,这种情况只能用在不需要参数的程序。
NOTE: 当对args确定了正确的分隔符后,shlex.split()就很有用,特别是在复杂的情况下:
>>>
>>> import shlex, subprocess
>>> command_line = raw_input()
/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
>>> args = shlex.split(command_line)
>>> print args
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
>>> p = subprocess.Popen(args) # Success!
NOTE: 选项(如 -input) 和 参数(如 eggs.txt) 在shell中是用空格分隔成分离的列表元素。
如果参数需要引号或反斜线,则它们会是一个单一列表元素。
shell参数(默认值为False)声明了是否使用shell来执行程序。
如果 shell=True, 它将args看作是一个字符串,而不是一个序列。
在Unix系统,且 shell=True时,shell默认使用 /bin/sh.
如果 args是一个字符串,则它声明了通过shell执行的命令。这意味着,字符串必须要使用正确的格式。
如果 args是一个序列,则第一个元素就是命令字符串,而其它的元素都作为参数使用。
可以这样说,Popen等价于:
Popen(['/bin/sh', '-c', args[0], args[1], ...])
bufsize: 如果指定了值,则它和内建函数 open()对应的参数有相同的意义:
0 -- 表示不缓冲
1 -- 表示缓冲
任何其它的正数值表示buffer的大小。
负数值表示使用系统默认值,通常表示完全缓冲。
它的默认值为零。
NOTE: 如果遇到性能问题,建议将bufsize设置成 -1 或足够大的正数(如 4096)。
executable: 指定了用于代替执行的程序。它极少会用到。
stdin, stdout, stderr:指定了执行程序的标准输入,标准输出和标准错误的文件句柄。
有效的值可以是 PIPE, 一个存在的文件描述符,或存在的文件对象,或 None.
默认值为 None。
stderr可以设置成STDOUT, 它表示将子进程的stderr数据重定向到stdout.
preexec_fn: 如果它被设置成可调用对象,那么这个对象会在子进程执行前被子进程调用,只用于Unix.
close_fds: 如果设置为True, 则在子进程被执行前,除0,1和2之外的所有文件描述符都将被关闭,只用于Unix。
cwd: 当它不为 None时,子程序在执行前,它的当前路径会被替换成 cwd的值。
这个路径并不会被添加到可执行程序的搜索路径,所以cwd不能是相对路径。
env: 当它不为 None时,它是新进程的环境变量的映射。
可以用它来代替当前进程的环境。
universal_newlines: 为真时,文件对象 stdout和 stderr都被以文本文件的方式打开
示例代码:
1. Popen对象创建后,主程序不会自动等待子进程完成。
我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block):
import subprocess
child = subprocess.Popen(["ping","-c","5","www.google.com"])
print("parent process")
从运行结果中看到,父进程在开启子进程之后并没有等待child的完成,而是直接运行print。
2. 对比等待的情况:
import subprocess
child = subprocess.Popen(["ping","-c","5","www.google.com"])
child.wait()
print("parent process")
此外,你还可以在父进程中对子进程进行其它操作,比如我们上面例子中的child对象:
child.poll() # 检查子进程状态
child.kill() # 终止子进程
child.send_signal() # 向子进程发送信号
child.terminate() # 终止子进程
子进程的PID存储在child.pid
3. 可以在Popen()建立子进程的时候改变标准输入、标准输出和标准错误,
并可以利用subprocess.PIPE将多个子进程的输入和输出连接在一起,构成管道(pipe):
import subprocess
child1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
child2 = subprocess.Popen(["wc"], stdin=child1.stdout,stdout=subprocess.PIPE)
out = child2.communicate()
print(out)
subprocess.PIPE实际上为文本流提供一个缓存区。
child1的stdout将文本输出到缓存区,随后child2的stdin从该PIPE中将文本读取走。
child2的输出文本也被存放在PIPE中,直到communicate()方法从PIPE中读取出PIPE中的文本。
要注意的是,communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成。
4. 还可以利用communicate()方法来使用PIPE给子进程输入:
import subprocess
child = subprocess.Popen(["cat"], stdin=subprocess.PIPE)
child.communicate("vamei")
我们启动子进程之后,cat会等待输入,直到我们用communicate()输入"vamei"。
通过使用subprocess包,我们可以运行外部程序。这极大的拓展了Python的功能。
如果你已经了解了操作系统的某些应用,你可以从Python中直接调用该应用(而不是完全依赖Python),
并将应用的结果输出给Python,并让Python继续处理。
shell的功能(比如利用文本流连接各个应用),就可以在Python中实现。
1.1.3.异常
在开始执行新程序之前,子进程抛出的异常,会被重新抛出到父进程。
另外,异常对象会有一个额外的属性,叫做 child_traceback, 它是一个字符串,包含从子程序的观察点追踪到的信息。
最常见的抛出的异常是 OSError, 当它发生时,通常是我们执行了一个不存在的文件。应用程序应当要能处理这个异常。
如果使用无效的参数调用 Popen,会抛出 ValueError异常。
如果被调用进程的返回码不为零,则check_call()和check_output()会抛出 CalledProcessError异常。
1.1.4. 安全
Unlike some other popen functions, this implementation will never call a system shell implicitly.
This means that all characters, including shell metacharacters, can safely be passed to child processes.
Obviously, if the shell is invoked explicitly, then it is the application’s responsibility to ensure that
all whitespace and metacharacters are quoted appropriately.
13) logging
将日志打印到屏幕
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import logging 5 6 logging.debug("This is debug message.") 7 logging.info("This is info message.") 8 logging.warn("This warning message.") 9 logging.error("This is error message.") 10 logging.critical("This is critical message.")
输出结果:
1 WARNING:root:This warning message. 2 ERROR:root:This is error message. 3 CRITICAL:root:This is critical message.
默认情况下,logging将日志打印到屏幕,日志级别为warning。
日志级别大小关系为:CRITICAL > ERROR > WARNING > INFO > DEBUG
通过 logging.basicConfig 函数对日志的输出格式及方式做相关配置
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import logging 5 6 logging.basicConfig(level=logging.DEBUG, 7 format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', 8 datefmt='%a, %d %b %Y %H:%M:%S', 9 filename='mylog.log', 10 filemode='w') 11 12 logging.debug("This is debug message.") 13 logging.info("This is info message.") 14 logging.warn("This warning message.") 15 logging.error("This is error message.") 16 logging.critical("This is critical message.")
输出文件中的内容为:
1 Fri, 18 Nov 2016 23:19:16 re_module.py[line:12] DEBUG This is debug message. 2 Fri, 18 Nov 2016 23:19:16 re_module.py[line:13] INFO This is info message. 3 Fri, 18 Nov 2016 23:19:16 re_module.py[line:14] WARNING This warning message. 4 Fri, 18 Nov 2016 23:19:16 re_module.py[line:15] ERROR This is error message. 5 Fri, 18 Nov 2016 23:19:16 re_module.py[line:16] CRITICAL This is critical message.
logging.basicConfig 函数参数说明
- filename: 指定日志文件名
- filemode: 和 file 函数意义相同,指定日志文件的打开模式,'w'或'a'
- format: 指定输出的格式和内容,format可以输出很多有用信息,如上例所示:
- %(name)s: logger 的名字
- %(levelno)s: 打印日志级别的数值
- %(levelname)s: 打印日志级别名称
- %(pathname)s: 打印当前执行程序的路径,其实就是 sys.argv[0]
- %(filename)s: 打印当前执行程序名
- %(funcName)s: 打印日志的当前函数
- %(lineno)d: 打印日志的当前行号
- %(asctime)s: 打印字符串形式的日志时间,默认格式是 “2016-11-19 00:06:49,620”,逗号后面的是毫秒
- %(created)f: 当前时间,用 UNIX 标准的表示时间的浮点数表示
- %(relativeCreated)d: 输出日志信息时的,自 Logger 创建以来的毫秒数
- %(thread)d: 打印线程 ID
- %(threadName)s: 打印线程名称
- %(process)d: 打印进程 ID
- %(message)s: 打印日志信息
- datefmt: 指定时间格式,同 time.strftime()
- level: 设置日志级别,默认为 logging.WARNING
- stream: 指定将日志的输出流,可以指定输出到 sys.stderr,sys.stdout 或者文件,默认输出到 sys.stderr,当 stream 和 filenam e同时指定时,stream 被忽略
将日志同时输出到文件和屏幕
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import logging 5 6 logging.basicConfig(level=logging.DEBUG, 7 format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', 8 datefmt='%a, %d %b %Y %H:%M:%S', 9 filename='mylog.log', 10 filemode='w') 11 12 ################################################################################################### 13 # 定义一个StreamHandler,将INFO级别或更高的日志信息打印到标准错误,并将其添加到当前的日志处理对象 14 console = logging.StreamHandler() 15 console.setLevel(logging.INFO) 16 formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') 17 console.setFormatter(formatter) 18 logging.getLogger('').addHandler(console) 19 ################################################################################################### 20 21 logging.debug("This is debug message.") 22 logging.info("This is info message.") 23 logging.warn("This warning message.") 24 logging.error("This is error message.") 25 logging.critical("This is critical message.")
输出结果:
1 root : INFO This is info message. 2 root : WARNING This warning message. 3 root : ERROR This is error message. 4 root : CRITICAL This is critical message.
输出到文件中的内容:
1 Sat, 19 Nov 2016 00:27:17 re_module.py[line:20] DEBUG This is debug message. 2 Sat, 19 Nov 2016 00:27:17 re_module.py[line:21] INFO This is info message. 3 Sat, 19 Nov 2016 00:27:17 re_module.py[line:22] WARNING This warning message. 4 Sat, 19 Nov 2016 00:27:17 re_module.py[line:23] ERROR This is error message. 5 Sat, 19 Nov 2016 00:27:17 re_module.py[line:24] CRITICAL This is critical message.
logging之日志回滚
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import logging 5 from logging.handlers import RotatingFileHandler 6 7 ################################################################################################### 8 # 定义一个RotatingFileHandler,最多备份5个日志文件,每个日志文件最大10M 9 handler = RotatingFileHandler('mylog.log', maxBytes=10*1024*1024, backupCount=5) 10 handler.setLevel(logging.INFO) 11 formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') 12 handler.setFormatter(formatter) 13 logging.getLogger('').addHandler(handler) 14 ###################################################################################################
logging有一个日志处理的主对象,其它处理方式都是通过addHandler添加进去的。
logging的几种handle方式如下:
- logging.StreamHandler: 日志输出到流,可以是sys.stderr、sys.stdout或者文件
- logging.FileHandler: 日志输出到文件
- 日志回滚方式,实际使用时用RotatingFileHandler和TimedRotatingFileHandler
- logging.handlers.BaseRotatingHandler
- logging.handlers.RotatingFileHandler
- logging.handlers.TimedRotatingFileHandler
- logging.handlers.SocketHandler: 远程输出日志到TCP/IP sockets
- logging.handlers.DatagramHandler: 远程输出日志到UDP sockets
- logging.handlers.SMTPHandler: 远程输出日志到邮件地址
- logging.handlers.SysLogHandler: 日志输出到syslog
- logging.handlers.NTEventLogHandler: 远程输出日志到Windows NT/2000/XP的事件日志
- logging.handlers.MemoryHandler: 日志输出到内存中的制定buffer
- logging.handlers.HTTPHandler: 通过"GET"或"POST"远程输出到HTTP服务器
由于StreamHandler和FileHandler是常用的日志处理方式,所以直接包含在logging模块中,而其他方式则包含在logging.handlers模块中
通过logging.config模块配置日志
logger.conf:
1 #logger.conf 2 ############################################### 3 [loggers] 4 keys=root,example01,example02 5 [logger_root] 6 level=DEBUG 7 handlers=hand01,hand02 8 [logger_example01] 9 handlers=hand01,hand02 10 qualname=example01 11 propagate=0 12 [logger_example02] 13 handlers=hand01,hand03 14 qualname=example02 15 propagate=0 16 ############################################### 17 [handlers] 18 keys=hand01,hand02,hand03 19 [handler_hand01] 20 class=StreamHandler 21 level=INFO 22 formatter=form02 23 args=(sys.stderr,) 24 [handler_hand02] 25 class=FileHandler 26 level=DEBUG 27 formatter=form01 28 args=('myapp.log', 'a') 29 [handler_hand03] 30 class=handlers.RotatingFileHandler 31 level=INFO 32 formatter=form02 33 args=('myapp.log', 'a', 10*1024*1024, 5) 34 ############################################### 35 [formatters] 36 keys=form01,form02 37 [formatter_form01] 38 format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s 39 datefmt=%a, %d %b %Y %H:%M:%S 40 [formatter_form02] 41 format=%(name)-12s: %(levelname)-8s %(message)s 42 datefmt=
示例一:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import logging 5 import logging.config 6 7 logging.config.fileConfig("logger.conf") 8 logger = logging.getLogger("example01") 9 10 logger.debug('This is debug message.') 11 logger.info('This is info message.') 12 logger.warn('This is warning message.')
输出结果:
1 example01 : INFO This is info message. 2 example01 : WARNING This is warning message.
输出文件内容:
1 Sat, 19 Nov 2016 00:54:02 re_module.py[line:10] DEBUG This is debug message. 2 Sat, 19 Nov 2016 00:54:02 re_module.py[line:11] INFO This is info message. 3 Sat, 19 Nov 2016 00:54:02 re_module.py[line:12] WARNING This is warning message.
示例二:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import logging 5 import logging.config 6 7 logging.config.fileConfig("logger.conf") 8 logger = logging.getLogger("example02") 9 10 logger.debug('This is debug message.') 11 logger.info('This is info message.') 12 logger.warn('This is warning message.')
输出结果:
1 example02 : INFO This is info message. 2 example02 : WARNING This is warning message.
输出文件内容:
1 example02 : INFO This is info message. 2 example02 : WARNING This is warning message.
logging是线程安全的
14) re 正则表达式
正则表达式是一个特殊的字符序列,他它能帮你方便的检查一个字符串是否与某种模式匹配。
re 模块使 Python 语言拥有全部的正则表达式功能。
compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。
re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。
re.match 函数
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match() 就返回 none 。
函数语法:
re.match(pattern, string, flags=0)
函数参数说明:
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
匹配成功 re.match 方法返回一个匹配的对象,否则返回None。
可以使用 group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法 | 描述 |
---|---|
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组 |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号 |
实例1:
1 >>> import re 2 >>> re.match('www', 'www.chblogs.com') # 在起始位置匹配 3 <_sre.SRE_Match object; span=(0, 3), match='www'> 4 >>> re.match('www', 'www.chblogs.com').span() # 在起始位置匹配 5 (0, 3) 6 >>> re.match('com', 'www.chblogs.com') # 不在起始位置匹配 7 >>>
实例2:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import re 5 6 line = "Cats are smarter than dogs." 7 8 matchObj = re.match(r'(.*) are (.*) .*', line, re.M|re.I) 9 10 if matchObj: 11 print("matchObj.group():", matchObj.group()) 12 print("matchObj.group(1):", matchObj.group(1)) 13 print("matchObj.group(2):", matchObj.group(2)) 14 else: 15 print("No match!")
输出结果:
1 matchObj.group(): Cats are smarter than dogs. 2 matchObj.group(1): Cats 3 matchObj.group(2): smarter than
re.search 方法
re.search 扫描整个字符串并返回第一个成功的匹配。
函数语法:
re.search(pattern, string, flags=0)
函数参数说明:
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等 |
匹配成功 re.search 方法返回一个匹配的对象,否则返回None。
可以使用 group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法 | 描述 |
---|---|
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组 |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号 |
实例1:
1 >>> import re 2 >>> re.search('www', 'www.cnblogs.com') 3 <_sre.SRE_Match object; span=(0, 3), match='www'> 4 >>> re.search('www', 'www.cnblogs.com').span() 5 (0, 3) 6 >>> re.search('com', 'www.cnblogs.com') 7 <_sre.SRE_Match object; span=(12, 15), match='com'> 8 >>> re.search('com', 'www.cnblogs.com').span() 9 (12, 15)
实例2:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import re 5 6 line = "Cats are smarter than dogs." 7 8 searchObj = re.search(r'(.*) are (.*) .*', line, re.M|re.I) 9 10 if searchObj: 11 print("searchObj.group():", searchObj.group()) 12 print("searchObj.group(1):", searchObj.group(1)) 13 print("searchObj.group(2):", searchObj.group(2)) 14 else: 15 print("Nothing found!")
输出结果:
1 searchObj.group(): Cats are smarter than dogs. 2 searchObj.group(1): Cats 3 searchObj.group(2): smarter than
re.match与re.search的区别
re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而 re.search 匹配整个字符串,直到找到一个匹配。
实例:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import re 5 6 line = "Cats are smarter than dogs." 7 8 matchObj = re.match(r'dogs', line, re.M|re.I) 9 if matchObj: 10 print("match --> matchObj.group():", matchObj.group()) 11 else: 12 print("No match!") 13 14 searchObj = re.search(r'dogs', line, re.M|re.I) 15 if searchObj: 16 print("search --> searchObj.group():", searchObj.group()) 17 else: 18 print("No match!")
输出结果:
1 No match! 2 search --> searchObj.group(): dogs
检索和替换
Python 的 re 模块提供了re.sub 用于替换字符串中的匹配项。
语法:
re.sub(pattern, repl, string, count=0, flags=0)
参数:
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
实例:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import re 5 6 phone = "2004-959-559 # 这是一个国外电话号码" 7 8 # 删除字符串中的 Python 注释 9 num = re.sub(r'#.*$', "", phone) 10 print("电话号码是:", num) 11 12 # 删除非数字(-)的字符串 13 num = re.sub(r'\D', "", phone) 14 print("电话号码是:", num)
输出结果:
1 电话号码是: 2004-959-559 2 电话号码是: 2004959559
当 repl 参数是一个函数时:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import re 5 6 7 # 将匹配的数字乘于 2 8 def double(matched): 9 value = int(matched.group('value')) 10 return str(value * 2) 11 12 s = 'A23G4HFD567' 13 print(re.sub('(?P<value>\d+)', double, s))
输出结果:
1 A46G8HFD1134
正则表达式修饰符 - 可选标志
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
正则表达式模式
模式字符串使用特殊的语法来表示一个正则表达式:
字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。
多数字母和数字前加一个反斜杠时会拥有不同的含义。
标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。
反斜杠本身需要使用反斜杠转义。
由于正则表达式通常都包含反斜杠,所以最好使用原始字符串来表示它们。模式元素(如 r'/t',等价于'//t')匹配相应的特殊字符。
下表列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。
模式 | 描述 |
---|---|
^ | 匹配字符串的开头 |
$ | 匹配字符串的末尾 |
. | 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符 |
[...] | 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k' |
[^...] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符 |
re* | 匹配0个或多个的表达式 |
re+ | 匹配1个或多个的表达式 |
re? | 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 |
re{n} | 精确匹配n个前面表达式 |
re{n,} | 精确匹配n个前面表达式 |
re{n, m} | 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式 |
a|b | 匹配a或b |
(re) | G匹配括号内的表达式,也表示一个组 |
(?imx) | 正则表达式包含三种可选标志:i, m, 或 x ,只影响括号中的区域 |
(?-imx) | 正则表达式关闭 i, m, 或 x 可选标志,只影响括号中的区域。 |
(?: re) | 类似 (...), 但是不表示一个组 |
(?imx: re) | 在括号中使用i, m, 或 x 可选标志 |
(?-imx: re) | 在括号中不使用i, m, 或 x 可选标志 |
(?#...) | 注释. |
(?= re) | 前向肯定界定符,如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败,但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边 |
(?! re) | 前向否定界定符,与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功 |
(?> re) | 匹配的独立模式,省去回溯 |
\w | 匹配字母数字及下划线 |
\W | 匹配非字母数字及下划线 |
\s | 匹配任意空白字符,等价于 [\t\n\r\f]. |
\S | 匹配任意非空字符 |
\d | 匹配任意数字,等价于 [0-9]. |
\D | 匹配任意非数字 |
\A | 匹配字符串开始 |
\Z | 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。c |
\z | 匹配字符串结束 |
\G | 匹配最后匹配完成的位置 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置,例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er' |
\B | 匹配非单词边界,'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er' |
\n, \t, 等. | 匹配一个换行符,匹配一个制表符等 |
\1...\9 | 匹配第n个分组的子表达式 |
\10 | 匹配第n个分组的子表达式,如果它经匹配。否则指的是八进制字符码的表达式 |
正则表达式实例
字符匹配
实例 | 描述 |
---|---|
python | 匹配 "python". |
字符类
实例 | 描述 |
---|---|
[Pp]ython | 匹配 "Python" 或 "python" |
rub[ye] | 匹配 "ruby" 或 "rube" |
[aeiou] | 匹配中括号内的任意一个字母 |
[0-9] | 匹配任何数字。类似于 [0123456789] |
[a-z] | 匹配任何小写字母 |
[A-Z] | 匹配任何大写字母 |
[a-zA-Z0-9] | 匹配任何字母及数字 |
[^aeiou] | 除了aeiou字母以外的所有字符 |
[^0-9] | 匹配除了数字外的字符 |
特殊字符类
实例 | 描述 |
---|---|
. | 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式 |
\d | 匹配一个数字字符,等价于 [0-9] |
\D | 匹配一个非数字字符,等价于 [^0-9] |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等,等价于 [ \f\n\r\t\v] |
\S | 匹配任何非空白字符,等价于 [^ \f\n\r\t\v] |
\w | 匹配包括下划线的任何单词字符,等价于'[A-Za-z0-9_]' |
\W | 匹配任何非单词字符,等价于 '[^A-Za-z0-9_]' |
本节作业
开发一个简单的python计算器
- 实现加减乘除及拓号优先级解析
- 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似功能偷懒实现),运算后得出结果,结果必须与真实的计算器所得出的结果一致
hint:
re.search(r'\([^()]+\)',s).group()
'(-40/5)'