Python基础学习07-模块
模块
一、模块基础
1、定义
模块:用来从逻辑上组织python代码(变量、函数、类、逻辑:目的是实现一个功能 ),本质就是.py结尾的python文件(文件名:test.py,对应的模块名:test)
包:用来从逻辑上组织模块的,本质就是一个目录(必须带有一个__init__.py的文件)
2、导入方法
import module_name (导入一个模块)
import module_name_1,module_name_2(导入多个模块用逗号分隔)
from module_name import * (导入模块内的全部方法、变量、函数)
from module_name import logger as logger_module (当导入模块中的函数或变量与本模块中的函数或变量冲突时用as重命名)
3、import的本质:
import 模块的本质:
import module_name 其本质是:将module_name.py文件解释运行了一遍,并把这个模块运行的结果赋值给了module_name这个变量
from module_name import x 其本质是:将 module_name.py中的代码里的x变量,放到了当前位置,执行了一遍
导入模块的本质就是找到模块并把python文件解释一遍
import module_name,一定要找到一个名为module_name.py的文件,找文件一定要知道文件夹路径(一般默认查找:当前路径、sys.path)
import os
os.path.abspath(__file__) #获取当前文件的绝对路径
os.path.dirname(os.path.abspath(__file__)) #获取当前文件的目录名
os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #获取上一级目录名
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) #追加到环境变量列表的结尾
import 包的本质:
导入包的本质就是找到包执行该包下的__init__.py文件
import package #相当于run __init__.py 因此若想导入一个包下的模块,需要修改这个包的__init__.py文件
#在__init__.py文件中from . import module_name
模块的分类:
a、标准库:内置模块,python解释器自带,拿过来就用
b、开源模块:第三方模块
c、自定义模块:自己定义的模块
二、内置模块
1、time与datetime模块
在Python中,通常有这几种方式来表示时间:
a、格式化的时间字符串(Format String)
b、时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。
c、结构化的时间(struct_time):struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)
1 import time 2 print(time.strftime("%Y-%m-%d %X")) #格式化的时间字符串:2018-05-24 20:48:10 3 print(time.time()) # 时间戳:1527166090.1953392 4 print(time.localtime()) #本地时区的struct_time:time.struct_time(tm_year=2018, tm_mon=5, tm_mday=24, tm_hour=20, tm_min=48, tm_sec=10, tm_wday=3, tm_yday=144, tm_isdst=0) 5 print(time.gmtime()) #UTC时区的struct_time:time.struct_time(tm_year=2018, tm_mon=5, tm_mday=24, tm_hour=12, tm_min=48, tm_sec=10, tm_wday=3, tm_yday=144, tm_isdst=0)
1 %a Locale’s abbreviated weekday name. 2 %A Locale’s full weekday name. 3 %b Locale’s abbreviated month name. 4 %B Locale’s full month name. 5 %c Locale’s appropriate date and time representation. 6 %d Day of the month as a decimal number [01,31]. 7 %H Hour (24-hour clock) as a decimal number [00,23]. 8 %I Hour (12-hour clock) as a decimal number [01,12]. 9 %j Day of the year as a decimal number [001,366]. 10 %m Month as a decimal number [01,12]. 11 %M Minute as a decimal number [00,59]. 12 %p Locale’s equivalent of either AM or PM. (1) 13 %S Second as a decimal number [00,61]. (2) 14 %U Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0. (3) 15 %w Weekday as a decimal number [0(Sunday),6]. 16 %W Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0. (3) 17 %x Locale’s appropriate date representation. 18 %X Locale’s appropriate time representation. 19 %y Year without century as a decimal number [00,99]. 20 %Y Year with century as a decimal number. 21 %z Time zone offset indicating a positive or negative time difference from UTC/GMT of the form +HHMM or -HHMM, where H represents decimal hour digits and M represents decimal minute digits [-23:59, +23:59]. 22 %Z Time zone name (no characters if no time zone exists). 23 %% A literal ‘%‘ character.
格式化字符串的时间格式
time模块
1 import time 2 print(time.time()) #获取时间戳:1527167372.0 3 time.sleep(0.1) #休眠0.1s 4 5 print(time.gmtime(1527167372.0)) #将时间戳转换为结构化的时间:(转换成的是utc时区的时间)如果参数未提供,则以当前时间为准 6 # time.struct_time(tm_year=2018, tm_mon=5, tm_mday=24, tm_hour=13, tm_min=9, tm_sec=32, tm_wday=3, tm_yday=144, tm_isdst=0) 7 print(time.localtime(1527167372.0)) # #将时间戳转换为结构化的时间:(转换成的是本地时区的时间)如果参数未提供,则以当前时间为准 8 #time.struct_time(tm_year=2018, tm_mon=5, tm_mday=24, tm_hour=21, tm_min=9, tm_sec=32, tm_wday=3, tm_yday=144, tm_isdst=0) 9 10 print(time.mktime(time.localtime()))#将一个结构化的时间转化为时间戳:1527167372.0 11 12 print(time.strftime("%Y-%m-%d %X", time.localtime()))#2018-05-24 21:18:02 13 # strftime(format[, t]) : 把一个代表时间的元组或者结构化的时间(如由time.localtime()和 time.gmtime()返回)转化为格式化的时间字符串。 14 # 如果t未指定,将传入time.localtime()。如果元组中任何一个元素越界,ValueError的错误将会被抛出。 15 16 print(time.strptime(‘2018-05-24 21:21:00‘, ‘%Y-%m-%d %X‘)) #把一个格式化时间字符串转化为结构化的时间。实际上它和strftime()是逆操作。 17 #time.struct_time(tm_year=2018, tm_mon=5, tm_mday=24, tm_hour=21, tm_min=21, tm_sec=0, tm_wday=3, tm_yday=144, tm_isdst=-1) 18 #在这个函数中,format默认为:"%a %b %d %H:%M:%S %Y"。 19 20 print(time.asctime())#Thu May 24 21:21:01 2018 21 # 把一个表示时间的元组或者struct_time表示为这种形式:‘Thu May 24 21:21:01 2018‘,如果没有参数,将会将time.localtime()作为参数传入。 22 23 print(time.ctime()) # Thu May 24 21:21:01 2018 24 print(time.ctime(time.time())) # Thu May 24 21:21:01 2018 25 # 把一个时间戳转化为time.asctime()的形式。如果参数未给或者为None的时候,将会默认time.time()为参数。 26 # 它的作用相当于time.asctime(time.localtime(secs))。
datetime模块
1 #时间加减 2 import datetime,time 3 4 print(datetime.datetime.now()) #返回 2018-05-24 21:39:23.444828 5 print(datetime.date.fromtimestamp(time.time()) ) # 时间戳直接转成日期格式 2018-05-24 6 print(datetime.datetime.now() ) 7 print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间+3天 8 print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间-3天 9 print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间+3小时 10 print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间+30分 11 12 c_time = datetime.datetime.now() #2018-05-24 21:39:23.445329 13 print(c_time.replace(minute=3,hour=2)) #时间替换 2018-05-24 02:03:23.445329
2、random模块
1 import random 2 3 print(random.random())#(0,1) 大于0且小于1之间的小数 :0.39322977107276613 4 print(random.randint(1,4)) #[1,4] 大于等于1且小于等于4之间的整数 5 print(random.randrange(1,4)) #[1,4) 大于等于1且小于4之间的整数 6 print(random.choice([1,‘aa‘,[4,5]]))#1或者aa或者[4,5] 7 print(random.sample([1,‘aa‘,[4,5]],2))#列表元素任意2个组合 8 print(random.uniform(1,3))#大于1小于3的小数,如1.927109612082716 9 item=[2,4,6,7,9] 10 random.shuffle(item) #打乱item的顺序,相当于"洗牌" 11 print(item)
1 import random 2 checkcode = ‘‘ 3 for i in range(4): 4 current = random.randrange(0,4) 5 if current != i: 6 temp = chr(random.randint(65,90)) 7 else: 8 temp = random.randint(0,9) 9 checkcode += str(temp) 10 print(checkcode)
生成随机验证码
3、os模块
1 import os 2 print(os.getcwd())# 获取当前工作目录,即当前python脚本工作的目录路径 3 print(os.chdir("\zz")) #改变当前脚本工作目录;相当于shell下cd 4 print(os.curdir) # 返回当前目录: (‘.‘) 5 print(os.pardir) # 获取当前目录的父目录字符串名:(‘..‘) 6 os.makedirs(‘D:\zz\模块\dirname1\dirname2‘) # 可生成多层递归目录 7 os.removedirs(‘D:\zz\模块\dirname1\dirname2‘) # 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 8 os.mkdir(‘dirname‘) # 生成单级目录;相当于shell中mkdir dirname 9 os.rmdir(‘dirname‘) # 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname 10 os.listdir(‘dirname‘) # 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 11 os.remove() # 删除一个文件 12 os.rename("oldname","newname")# 重命名文件/目录 13 os.stat(‘path/filename‘) # 获取文件/目录信息 14 print(os.sep ) # 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/" 15 print(os.linesep) # 输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n" 16 print(os.pathsep) # 输出用于分割文件路径的字符串 win下为;,Linux下为: 17 print(os.name) # 输出字符串指示当前使用平台。win->‘nt‘; Linux->‘posix‘ 18 os.system("ipconfig /all") # 运行shell命令,直接显示 19 print(os.environ) #获取系统环境变量 20 print(os.path.abspath(__file__)) #返回path规范化的绝对路径,返回当前文件的绝对路径 21 print(os.path.split(‘\zz\作业\模块\os模块.py‘)) #将path分割成目录和文件名二元组返回:(‘\\zz\\作业\\模块‘, ‘os模块.py‘) 22 print(os.path.dirname(‘\zz\作业\模块\os模块.py‘)) # 返回path的目录。其实就是os.path.split(path)的第一个元素 23 print(os.path.basename(‘\zz\作业\模块\os模块.py‘)) # 返回path最后的文件名。如果path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 24 os.path.exists(path) # 如果path存在,返回True;如果path不存在,返回False 25 os.path.isabs(path) #如果path是绝对路径,返回True 26 os.path.isfile(path)# 如果path是一个存在的文件,返回True。否则返回False 27 os.path.isdir(path) # 如果path是一个存在的目录,则返回True。否则返回False 28 os.path.join(path1[, path2[, ...]])# 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 29 os.path.getatime(path) # 返回path所指向的文件或者目录的最后存取时间 30 os.path.getmtime(path) # 返回path所指向的文件或者目录的最后修改时间 31 os.path.getsize(path)# 返回path的大小
1 #方式一:推荐使用 2 import os 3 #具体应用 4 import os,sys 5 6 possible_topdir = os.path.normpath(os.path.join( 7 os.path.abspath(__file__), 8 os.pardir, #上一级 9 os.pardir, 10 os.pardir 11 )) 12 print(possible_topdir) 13 sys.path.insert(0,possible_topdir) 14 15 #方式二:不推荐使用 16 print(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
os路径处理
4、sys模块
1 import sys 2 print(sys.argv) #命令行参数List,第一个元素是程序本身路径 3 # sys.exit(0) #退出程序,正常退出时exit(0) 4 print(sys.version) #获取Python解释程序的版本信息 5 print(sys.path) #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 6 print(sys.platform ) #返回操作系统平台名称 7 sys.stdout.write(‘please:‘) 8 val = sys.stdin.readline()[:-1]
5、shutil模块
高级的 文件、文件夹、压缩包 处理模块
1 import shutil 2 3 shutil.copyfileobj(fsrc, fdst[, length]) # 将文件内容拷贝到另一个文件中 4 shutil.copyfileobj(open(‘old.xml‘,‘r‘), open(‘new.xml‘, ‘w‘)) 5 6 shutil.copyfile(src, dst)# 拷贝文件 7 shutil.copyfile(‘f1.log‘, ‘f2.log‘) #目标文件无需存在 8 9 shutil.copymode(src, dst)# 仅拷贝权限。内容、组、用户均不变# 10 shutil.copymode(‘f1.log‘, ‘f2.log‘) #目标文件必须存在 11 12 shutil.copystat(src, dst)# 仅拷贝状态的信息,包括:mode bits, atime, mtime, flags 13 shutil.copystat(‘f1.log‘, ‘f2.log‘) #目标文件必须存在 14 15 shutil.copy(src, dst)# 拷贝文件和权限 16 shutil.copy(‘f1.log‘, ‘f2.log‘) 17 18 shutil.copy2(src, dst)# 拷贝文件和状态信息 19 shutil.copy2(‘f1.log‘, ‘f2.log‘) 20 21 shutil.ignore_patterns(*patterns) 22 shutil.copytree(src, dst, symlinks=False, ignore=None) 23 # 递归的去拷贝文件夹 24 shutil.copytree(‘folder1‘, ‘folder2‘, ignore=shutil.ignore_patterns(‘*.pyc‘, ‘tmp*‘)) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除 25 26 shutil.rmtree(path[, ignore_errors[, onerror]])# 递归的去删除文件 27 shutil.rmtree(‘folder1‘) 28 29 shutil.move(src, dst)# 递归的去移动文件,它类似mv命令,其实就是重命名。 30 shutil.move(‘folder1‘, ‘folder3‘) 31 32 33 34 shutil.make_archive(base_name, format,...) 35 ‘‘‘ 36 创建压缩包并返回文件路径,例如:zip、tar 37 创建压缩包并返回文件路径,例如:zip、tar 38 base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径, 39 如 data_bak =>保存至当前路径 40 如:/tmp/data_bak =>保存至/tmp/ 41 format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar” 42 root_dir: 要压缩的文件夹路径(默认当前目录) 43 owner: 用户,默认当前用户 44 group: 组,默认当前组 45 logger: 用于记录日志,通常是logging.Logger对象 46 ‘‘‘ 47 import shutil 48 ret = shutil.make_archive("data_bak", ‘gztar‘, root_dir=‘/data‘) #将 /data 下的文件打包放置当前程序目录 49 rec = shutil.make_archive("/tmp/data_bak", ‘gztar‘, root_dir=‘/data‘) #将 /data下的文件打包放置 /tmp/目录 50 # shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的
6、json&pickle模块
eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用了,所以eval的重点还是通常用来执行一个字符串表达式,并返回表达式的值。
1 import json 2 x="[null,true,false,1]" 3 print(eval(x)) #报错,无法解析null类型,而json就可以 4 print(json.loads(x))
一个软件/程序的执行就是在处理一系列状态的变化,在编程语言中,‘状态‘会以各种各样有结构的数据类型(也可简单的理解为变量)的形式被保存在内存中。内存是无法永久保存数据的,当程序运行了一段时间,我们断电或者重启程序,内存中关于这个程序的之前一段时间的数据(有结构)都被清空了。在断电或重启程序之前将程序当前内存中所有的数据都保存下来(保存到文件中),以便于下次程序执行能够从文件中载入之前的数据,然后继续执行,这就是序列化。序列化之后,不仅可以把序列化后的内容写入磁盘,还可以通过网络传输到别的机器上,如果收发的双方约定好使用一种序列化的格式,那么便打破了平台/语言差异化带来的限制,实现了跨平台数据交互。
序列化:我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化。在Python中叫pickling。
反序列化:反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
用处:1、持久保存状态;2、跨平台数据交互
python用于序列化的两个模块:
json:用于字符串 和 python数据类型间进行转换
pickle:用于python特有的类型 和 python的数据类型间进行转换
Json模块提供了四个功能:dumps、dump、loads、load
pickle模块提供了四个功能:dumps、dump、loads、load
1 import json 2 data_obj = {‘name‘:‘zz‘,‘age‘:13,‘sex‘:‘M‘} 3 """ 4 dumps:序列化一个对象 5 sort_keys:根据key排序 6 indent:以4个空格缩进,输出阅读友好型 7 ensure_ascii: 可以序列化非ascii码(中文等) 8 """ 9 s_dumps = json.dumps(data_obj, sort_keys=True, indent=4, ensure_ascii=False) 10 print(s_dumps) 11 # ---------------------------------------------------分割线------------------------------------------------------------ 12 """ 13 dump:将一个对象序列化存入文件 14 dump()的第一个参数是要序列化的对象,第二个参数是打开的文件句柄 15 注意打开文件时加上以UTF-8编码打开 16 * 运行此文件之后在统计目录下会有一个data.json文件,打开之后就可以看到json类型的文件应该是怎样定义的 17 """ 18 with open("data.json", "w", encoding="UTF-8") as f_dump: 19 s_dump = json.dump(data_obj, f_dump, ensure_ascii=False) 20 print(s_dump) 21 # ---------------------------------------------------分割线------------------------------------------------------------ 22 """ 23 load:从一个打开的文件句柄加载数据 24 注意打开文件的编码 25 """ 26 with open("data.json", "r", encoding="UTF-8") as f_load: 27 r_load = json.load(f_load) 28 print(r_load) 29 # ---------------------------------------------------分割线------------------------------------------------------------ 30 """ 31 loads: 从一个对象加载数据 32 """ 33 r_loads = json.loads(s_dumps) 34 print(r_loads) 35 # ---------------------------------------------------分割线------------------------------------------------------------ 36 # 说明 37 # dct="{‘1‘:111}"#json 不认单引号 38 # dct=str({"1":111})#报错,因为生成的数据还是单引号:{‘one‘: 1} 39 dct=‘{"1":"111"}‘ 40 print(json.loads(dct)) 41 # 无论数据是怎样创建的,只要满足json格式,就可以json.loads出来,不一定非要dumps的数据才能loads
json
1 import pickle 2 dic={‘name‘:‘zz‘,‘age‘:13,‘sex‘:‘M‘} 3 print(type(dic))#<class ‘dict‘> 4 j=pickle.dumps(dic) 5 print(type(j))#<class ‘bytes‘> 6 7 f=open(‘dic_pickle‘,‘wb‘)#注意是w是写入str,wb是写入bytes,j是‘bytes‘ 8 f.write(j) #-------------------等价于pickle.dump(dic,f) 9 f.close() 10 11 #-------------------------反序列化 12 f=open(‘dic_pickle‘,‘rb‘) 13 data=pickle.loads(f.read())# 等价于data=pickle.load(f) 14 print(data[‘age‘]) 15 """ 16 Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python 17 可能不同版本的Python彼此都不兼容 18 因此,只用Pickle保存那些不重要的数据 19 即使不能成功地反序列化也没关系。 20 """
pickle
7、shelve 模块
shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型;shelve模块是将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式
1 import shelve 2 3 f=shelve.open(r‘sheve.txt‘) 4 f[‘stu1_info‘]={‘name‘:‘aa‘,‘age‘:18,‘hobby‘:[‘p‘,‘s‘,‘d‘]} 5 f[‘stu2_info‘]={‘name‘:‘zz‘,‘age‘:13} 6 f[‘school_info‘]={‘web‘:‘http://www.pypy.com‘,‘city‘:‘beijing‘} 7 8 print(f[‘stu1_info‘][‘hobby‘]) 9 f.close()
8、xml模块
xml是实现不同语言或程序之间进行数据交换的协议,很多传统公司如金融行业的很多系统的接口还主要是xml。
xml的格式如下,就是通过<>节点来区别数据结构的:
1 <?xml version="1.0"?> 2 <data> 3 <country name="Liechtenstein"> 4 <rank updated="yes">2</rank> 5 <year>2008</year> 6 <gdppc>141100</gdppc> 7 <neighbor name="Austria" direction="E"/> 8 <neighbor name="Switzerland" direction="W"/> 9 </country> 10 <country name="Singapore"> 11 <rank updated="yes">5</rank> 12 <year>2011</year> 13 <gdppc>59900</gdppc> 14 <neighbor name="Malaysia" direction="N"/> 15 </country> 16 <country name="Panama"> 17 <rank updated="yes">69</rank> 18 <year>2011</year> 19 <gdppc>13600</gdppc> 20 <neighbor name="Costa Rica" direction="W"/> 21 <neighbor name="Colombia" direction="E"/> 22 </country> 23 </data>
1 import xml.etree.ElementTree as ET 2 3 tree = ET.parse("xmltest.xml") 4 root = tree.getroot() 5 print(root.tag) 6 7 #遍历xml文档 8 for country in root: 9 print(‘========>‘,country.tag,country.attrib,country.attrib[‘name‘]) 10 for i in country: 11 print(i.tag,i.attrib,i.text) 12 #只遍历year 节点 13 for node in root.iter(‘year‘): 14 print(node.tag,node.text) 15 #--------------------------------------- 16 #修改 17 for node in root.iter(‘year‘): 18 new_year=int(node.text)+1 19 node.text=str(new_year) 20 node.set(‘updated‘,‘yes‘) 21 node.set(‘version‘,‘1.0‘) 22 tree.write(‘test.xml‘) 23 24 #删除node 25 for country in root.findall(‘country‘): 26 rank = int(country.find(‘rank‘).text) 27 if rank > 50: 28 root.remove(country) 29 tree.write(‘output.xml‘) 30 31 #在country内添加(append)节点year2 32 for country in root.findall(‘country‘): 33 for year in country.findall(‘year‘): 34 if int(year.text) > 2000: 35 year2=ET.Element(‘year2‘) 36 year2.text=‘new‘ 37 year2.attrib={‘update‘:‘yes‘} 38 country.append(year2) #往country节点下添加子节点 39 tree.write(‘a.xml‘)
xml增删改查
1 import xml.etree.ElementTree as ET 2 new_xml = ET.Element("namelist") 3 name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) 4 age = ET.SubElement(name,"age",attrib={"checked":"no"}) 5 sex = ET.SubElement(name,"sex") 6 sex.text = ‘33‘ 7 name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"}) 8 age = ET.SubElement(name2,"age") 9 age.text = ‘19‘ 10 11 et = ET.ElementTree(new_xml) #生成文档对象 12 et.write("test.xml", encoding="utf-8",xml_declaration=True) 13 14 ET.dump(new_xml) #打印生成的格式
创建xml
9、configparser模块
用于生成和修改常见配置文档
1 import configparser 2 config = configparser.ConfigParser() 3 config["DEFAULT"] = {‘ServerAliveInterval‘: ‘45‘, 4 ‘Compression‘: ‘yes‘, 5 ‘CompressionLevel‘: ‘9‘} 6 config[‘bitbucket.org‘] = {} 7 config[‘bitbucket.org‘][‘User‘] = ‘hg‘ 8 config[‘topsecret.server.com‘] = {} 9 topsecret = config[‘topsecret.server.com‘] 10 topsecret[‘Host Port‘] = ‘50022‘ # mutates the parser 11 topsecret[‘ForwardX11‘] = ‘no‘ # same here 12 config[‘DEFAULT‘][‘ForwardX11‘] = ‘yes‘ 13 with open(‘example.ini‘, ‘w‘) as configfile: 14 config.write(configfile) 15
创建
1 import configparser 2 3 config=configparser.ConfigParser() 4 config.read(‘example.ini‘) 5 6 #查看所有的标题 7 res=config.sections() #[‘bitbucket.org‘, ‘topsecret.server.com‘] 8 print(res) 9 10 #查看标题bitbucket.org下所有key=value的key 11 options=config.options(‘bitbucket.org‘) 12 print(options) #[‘user‘, ‘compressionlevel‘, ‘serveraliveinterval‘, ‘compression‘, ‘forwardx11‘] 13 14 #查看标题bitbucket.org下所有key=value的(key,value)格式 15 item_list=config.items(‘bitbucket.org‘) 16 print(item_list) #[(‘compressionlevel‘, ‘9‘), (‘serveraliveinterval‘, ‘45‘), (‘compression‘, ‘yes‘), (‘forwardx11‘, ‘yes‘), (‘user‘, ‘hg‘)] 17 18 #查看标题bitbucket.org下user的值=>字符串格式 19 val=config.get(‘bitbucket.org‘,‘user‘) 20 print(val) #hg 21 22 #查看标题bitbucket.org下compressionlevel的值=>整数格式 23 val1=config.getint(‘bitbucket.org‘,‘compressionlevel‘) 24 print(val1) #9 25 26 #查看标题bitbucket.org下compression的值=>布尔值格式 27 val2=config.getboolean(‘bitbucket.org‘,‘compression‘) 28 print(val2) #True 29 30 31 #删除整个标题section2 32 config.remove_section(‘topsecret.server.com‘) 33 34 #删除标题bitbucket.org下的user 35 config.remove_option(‘bitbucket.org‘,‘user‘) 36 37 #判断是否存在某个标题 38 print(config.has_section(‘bitbucket.org‘)) 39 40 #判断标题bitbucket.org下是否有forwardx11 41 print(config.has_option(‘bitbucket.org‘,‘forwardx11‘)) 42 43 #添加一个标题 44 config.add_section(‘egon‘) 45 46 #在标题egon下添加name=egon,age=18的配置 47 config.set(‘egon‘,‘name‘,‘egon‘) 48 config.set(‘egon‘,‘age‘,‘18‘) #必须是字符串 49 50 #最后将修改的内容写入文件,完成最终的修改 51 config.write(open(‘a.ini‘,‘w‘))
configparser增删改查
10、hashlib模块
hash:hash是一种算法(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法),该算法接受传入的内容,经过运算得到一串hash值
特点:
a、 只要传入的内容一样,得到的hash值必然一样=====>用于明文传输密码文件完整性校验
b、不能由hash值返解成内容=====>把密码做成hash值,用于网络传输
c、只要使用的hash算法不变,无论校验的内容有多大,得到的hash值长度是固定的
1 import hashlib 2 3 m=hashlib.md5()# m=hashlib.sha256() 4 5 m.update(‘hello‘.encode(‘utf8‘)) 6 print(m.hexdigest()) #5d41402abc4b2a76b9719d911017c592 7 8 m.update(‘zz‘.encode(‘utf8‘)) 9 10 print(m.hexdigest()) #bcb13ffa8bb7b827b0ba99fce02ab86d 11 12 m2=hashlib.md5() 13 m2.update(‘hellozz‘.encode(‘utf8‘)) 14 print(m2.hexdigest()) #bcb13ffa8bb7b827b0ba99fce02ab86d 15 16 ‘‘‘ 17 注意:把一段很长的数据update多次,与一次update这段长数据,得到的结果一样 18 但是update多次为校验大文件提供了可能。 19 ‘‘‘
对加密算法中添加自定义key再来做加密:
1 import hashlib 2 hash = hashlib.md5(‘abcd‘.encode(‘utf8‘)) 3 hash.update(‘zz‘.encode(‘utf8‘)) 4 print (hash.hexdigest())#363110069610b4595ebb1596dd172517
1 #要想保证hmac最终结果一致,必须保证: 2 #1:hmac.new括号内指定的初始key一样 3 #2:无论update多少次,校验的内容累加到一起是一样的内容 4 import hmac 5 h1=hmac.new(b‘zz‘) 6 h1.update(b‘a‘) 7 h1.update(b‘b‘) 8 print(h1.hexdigest()) 9 10 h2=hmac.new(b‘zz‘) 11 h2.update(b‘ab‘) 12 print(h2.hexdigest()) 13 14 h3=hmac.new(b‘zzab‘) 15 print(h3.hexdigest()) 16 17 ‘‘‘ 18 60bf58ffc6dfe4e09579740e0b4c58b6 19 60bf58ffc6dfe4e09579740e0b4c58b6 20 c56b1689c5433fbee2cbab77a253ed29 21 ‘‘‘
hmac
11、re模块
正则:用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
模式 | 描述 |
\w | 匹配字母数字及下划线 |
\W | 匹配非字母数字及下划线 |
\s | 匹配任意空白字符,等价于 [\t\n\r\f]. |
\S | 匹配任意非空字符 |
\n | 匹配一个换行符 |
\t | 匹配一个制表符 |
\d | 匹配任意数字,等价于 [0-9] |
\D | 匹配任意非数字 |
\A | 匹配字符串开始 |
\Z | 匹配字符串结束 |
^ | 匹配字符串的开头 |
$ | 匹配字符串的末尾 |
. | 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符 |
[...] | 用来表示一组字符,单独列出:[amk] 匹配 ‘a‘,‘m‘或‘k‘ |
[^...] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符 |
* | 匹配0个或多个的表达式 |
+ | 匹配1个或多个的表达式 |
? | 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 |
{n} | 精确匹配 n 个前面表达式。例如, o{2} 不能匹配 "Bob" 中的 "o",但是能匹配 "food" 中的两个 o |
{n,} | 匹配 n 个前面表达式。例如, o{2,} 不能匹配"Bob"中的"o",但能匹配 "foooood"中的所有 o。"o{1,}" 等价于 "o+"。"o{0,}" 则等价于 "o*" |
{n, m} | 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式 |
a| b | 匹配a或b |
() | 分组:匹配括号内的表达式,也表示一个组 |
(?imx) | 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域 |
(?-imx) | 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域 |
(?: re) | 类似 (...), 但是不表示一个组 |
(?imx: re) | 在括号中使用i, m, 或 x 可选标志 |
(?-imx: re) | 在括号中不使用i, m, 或 x 可选标志 |
(?#...) | 注释 |
(?= re) | 前向肯定界定符。 |
(?! re) | 前向否定界定符 |
(?> re) | 匹配的独立模式,省去回溯 |
1 #正则匹配 2 import re 3 #\w:匹配字母数字及下划线与; 4 #\W:匹配非字母数字及下划线 5 print(re.findall(‘\w‘,‘runoob 123 google 456‘)) #[‘r‘, ‘u‘, ‘n‘, ‘o‘, ‘o‘, ‘b‘, ‘1‘, ‘2‘, ‘3‘, ‘g‘, ‘o‘, ‘o‘, ‘g‘, ‘l‘, ‘e‘, ‘4‘, ‘5‘, ‘6‘] 6 print(re.findall(‘\W‘,‘runoob 123 google 456‘)) #[‘ ‘, ‘ ‘, ‘ ‘] 7 8 #\s:匹配任意空白字符,等价于 [\t\n\r\f] 9 #\S:匹配任意非空字符 10 print(re.findall(‘\s‘,‘runoob 123 google 456‘)) #[‘ ‘, ‘ ‘, ‘ ‘] 11 print(re.findall(‘\s‘,‘runoob \n 123 \t google‘)) #[‘ ‘, ‘\n‘, ‘ ‘, ‘ ‘, ‘\t‘, ‘ ‘] #\n \t都是空,都可以被\s匹配 12 print(re.findall(‘\S‘,‘runoob 123 google 456‘)) #[‘r‘, ‘u‘, ‘n‘, ‘o‘, ‘o‘, ‘b‘, ‘1‘, ‘2‘, ‘3‘, ‘g‘, ‘o‘, ‘o‘, ‘g‘, ‘l‘, ‘e‘, ‘4‘, ‘5‘, ‘6‘] 13 14 #\n:匹配一个换行符 15 #\t:匹配一个制表符 16 print(re.findall(r‘\n‘,‘hello egon \n123‘)) #[‘\n‘] 17 print(re.findall(r‘\t‘,‘hello egon\t123‘)) #[‘\t‘] 18 19 #\d:匹配任意数字,等价于 [0-9] 20 #\D:匹配任意非数字 21 print(re.findall(‘\d‘,‘hello egon 123‘)) #[‘1‘, ‘2‘, ‘3‘] 22 print(re.findall(‘\D‘,‘hello \n egon 123‘)) #[‘h‘, ‘e‘, ‘l‘, ‘l‘, ‘o‘, ‘ ‘, ‘\n‘, ‘ ‘, ‘e‘, ‘g‘, ‘o‘, ‘n‘, ‘ ‘] 23 24 #\A:匹配字符串开始 25 #\Z:匹配字符串结束 26 print(re.findall(‘\Ahe‘,‘hello egon 123‘)) #[‘he‘],\A==>^ 27 print(re.findall(‘123\Z‘,‘hello egon 123‘)) #[‘he‘],\Z==>$ 28 29 #^:匹配字符串的开头 30 #$:匹配字符串的末尾 31 print(re.findall(‘^h‘,‘hello egon 123‘)) #[‘h‘] 32 print(re.findall(‘3$‘,‘hello egon 123‘)) #[‘3‘] 33 34 # 重复匹配: 35 # .:匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符 36 print(re.findall(‘a.b‘,‘a1b‘)) #[‘a1b‘] 37 print(re.findall(‘a.b‘,‘a1b a*b a b aaab‘)) #[‘a1b‘, ‘a*b‘, ‘a b‘, ‘aab‘] 38 print(re.findall(‘a.b‘,‘a\nb‘)) #[] 39 print(re.findall(‘a.b‘,‘a\nb‘,re.S)) #[‘a\nb‘] 40 print(re.findall(‘a.b‘,‘a\nb‘,re.DOTALL)) #[‘a\nb‘]同上一条意思一样 41 42 43 # *:匹配0个或多个的表达式 44 print(re.findall(‘ab*‘,‘bbbbbbb‘)) #[](b可以是0个或多个,但第一个必须是a) 45 print(re.findall(‘ab*‘,‘acc‘)) #[‘a‘] 46 print(re.findall(‘ab*‘,‘abbbb‘)) #[‘abbbb‘] 47 48 #+:匹配1个或多个的表达式 49 print(re.findall(‘ab+‘,‘a‘)) #[] 50 print(re.findall(‘ab+‘,‘abbb‘)) #[‘abbb‘] 51 52 #?:匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 53 print(re.findall(‘ab?‘,‘a‘)) #[‘a‘] 54 print(re.findall(‘ab?‘,‘abbb‘)) #[‘ab‘] 55 56 #匹配所有包含小数在内的数字 57 print(re.findall(‘\d+\.?\d*‘,"asdfasdf123as1.13dfa12adsf1asdf3")) #[‘123‘, ‘1.13‘, ‘12‘, ‘1‘, ‘3‘] 58 59 #.*默认为贪婪匹配 60 print(re.findall(‘a.*b‘,‘a1b22222222b‘)) #[‘a1b22222222b‘] 61 #.*?为非贪婪匹配:推荐使用 62 print(re.findall(‘a.*?b‘,‘a1b22222222b‘)) #[‘a1b‘] 63 64 #{n,m}:匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式 65 print(re.findall(‘ab{2}‘,‘abbb‘)) #[‘abb‘] 66 print(re.findall(‘ab{1,3}‘,‘abbb‘)) #[‘abbb‘] 67 print(re.findall(‘ab{1,}‘,‘abbb‘)) #‘ab{1,}‘ ===> ‘ab+‘ 68 print(re.findall(‘ab{0,}‘,‘abbb‘)) #‘ab{0,}‘ ===> ‘ab*‘ 69 70 #[...]:用来表示一组字符,单独列出:[amk] 匹配 ‘a‘,‘m‘或‘k‘ 71 #[^...]:不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符 72 print(re.findall(‘a[1*-]b‘,‘a1b a*b a-b‘)) #[]内的都为普通字符了,且如果-没有被转意的话,应该放到[]的开头或结尾:[‘a1b‘, ‘a*b‘, ‘a-b‘] 73 print(re.findall(‘a[^1*-]b‘,‘a1b a*b a-b a=b‘)) #[‘a=b‘] 74 print(re.findall(‘a[0-9]b‘,‘a1b a*b a-b a=b‘)) #[][‘a1b‘] 75 print(re.findall(‘a[a-z]b‘,‘a1b a*b a-b a=b aeb‘)) #[‘aeb‘] 76 print(re.findall(‘a[a-zA-Z]b‘,‘a1b a*b a-b a=b aeb aEb‘)) #[‘aeb‘, ‘aEb‘] 77 78 #|:匹配a或b 79 print(re.findall(‘compan(?:y|ies)‘,‘Too many companies have gone bankrupt, and the next one is my company‘)) #[‘companies‘, ‘company‘] 80 81 #():分组匹配括号内的表达式,也表示一个组 82 print(re.findall(‘ab+‘,‘ababab123‘)) #[‘ab‘, ‘ab‘, ‘ab‘] 83 print(re.findall(‘(ab)+123‘,‘ababab123‘)) #[‘ab‘],匹配到末尾的ab123中的ab 84 print(re.findall(‘(?:ab)+123‘,‘ababab123‘)) #findall的结果不是匹配的全部内容,而是组内的内容,?:可以让结果为匹配的全部内容 85 print(re.findall(‘href="(.*?)"‘,‘<a href="http://www.baidu.com">点击</a>‘))#[‘http://www.baidu.com‘] 86 print(re.findall(‘href="(?:.*?)"‘,‘<a href="http://www.baidu.com">点击</a>‘))#[‘href="http://www.baidu.com"‘] 87 88 89 90 ‘‘‘ 91 反斜杠的困扰:与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。 92 假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\"; 93 前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。 94 Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。 95 同样,匹配一个数字的"\\d"可以写成r"\d"。 96 有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。 97 ‘‘‘ 98 # print(re.findall(‘a\\c‘,‘a\c‘)) #对于正则来说a\\c确实可以匹配到a\c,但是在python解释器读取a\\c时,会发生转义,然后交给re去执行,所以抛出异常 99 print(re.findall(r‘a\\c‘,‘a\c‘)) #r代表告诉解释器使用rawstring,即原生字符串,把我们正则内的所有符号都当普通字符处理,不要转义 100 print(re.findall(‘a\\\\c‘,‘a\c‘)) #同上面的意思一样,和上面的结果一样都是[‘a\\c‘]
匹配模式
1 ‘‘‘ 2 最常用的匹配语法: 3 re.findall 把所有匹配到的字符放到列表中以元素返回 4 re.search 匹配包含 5 re.match 从头开始匹配 6 re.split 以匹配到的字符当做列表分隔符 7 re.sub 匹配字符并替换 8 ‘‘‘ 9 import re 10 print(re.findall(‘o‘,‘runoob 123 google 456‘) ) #[‘o‘, ‘o‘, ‘o‘, ‘o‘],返回所有满足匹配条件的结果,放在列表里 11 print(re.search(‘o‘,‘runoob 123 google 456‘).group()) #o,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。 12 print(re.match(‘o‘,‘runoob 123 google 456‘)) #None,同search,不过在字符串开始处进行匹配,完全可以用search+^代替match 13 print(re.split(‘[ab]‘,‘abcd‘)) #[‘‘, ‘‘, ‘cd‘],先按‘a‘分割得到‘‘和‘bcd‘,再对‘‘和‘bcd‘分别按‘b‘分割 14 print(‘===>‘,re.sub(‘o‘,‘A‘,‘runoob 123 google 456‘)) #===> runAAb 123 gAAgle 456,不指定n,默认替换所有 15 print(‘===>‘,re.sub(‘o‘,‘A‘,‘runoob 123 google 456‘,1)) #===> runAob 123 google 456 16 print(‘===>‘,re.sub(‘o‘,‘A‘,‘runoob 123 google 456‘,2)) #===> runAAb 123 google 456 17 print(‘===>‘,re.sub(‘^(\w+)(.*?\s)(\w+)(.*?\s)(\w+)(.*?)$‘,r‘\5\2\3\4\1‘,‘runoob 123 google‘)) #===> google 123 runoob 18 print(‘===>‘,re.subn(‘o‘,‘A‘,‘runoob 123 google 456‘)) #===> (‘runAAb 123 gAAgle 456‘, 4),结果带有总共替换的个数 19 obj=re.compile(‘\d{2}‘) 20 print(obj) 21 print(obj.search(‘abc123eeee‘).group()) #12 22 print(obj.findall(‘abc123eeee‘)) #[‘12‘],重用了obj 23 print(re.findall(r‘-?\d+\.?\d*‘,"1-12*(60+(-40.35/5)-(-4*3))")) #找出所有数字[‘1‘, ‘-12‘, ‘60‘, ‘-40.35‘, ‘5‘, ‘-4‘, ‘3‘] 24 #使用|,先匹配的先生效,|左边是匹配小数,而findall最终结果是查看分组,所以即使匹配成功小数也不会存入结果 25 #而不是小数时,就去匹配(-?\d+) 26 print(re.findall("-?\d+\.\d*|(-?\d+)","1-12*(60+(-40.35/5)-(-4*3))")) #找出所有整数[‘1‘, ‘-12‘, ‘60‘, ‘‘, ‘5‘, ‘-4‘, ‘3‘] 27 #为何同样的表达式search与findall却有不同结果: 28 print(re.search(‘\(([\+\-\*\/]*\d+\.?\d*)+\)‘,"1-12*(60+(-40.35/5)-(-4*3))").group()) #(-40.35/5) 29 print(re.findall(‘\(([\+\-\*\/]*\d+\.?\d*)+\)‘,"1-12*(60+(-40.35/5)-(-4*3))")) #[‘/5‘, ‘*3‘] 30 #看这个例子:(\d)+相当于(\d)(\d)(\d)(\d)...,是一系列分组 31 print(re.search(‘(\d)+‘,‘123‘).group()) #group的作用是将所有组拼接到一起显示出来 32 print(re.findall(‘(\d)+‘,‘123‘)) #findall结果是组内的结果,且是最后一个组的结果 33 34 s=‘‘‘ 35 http://www.baidu.com 36 [email protected] 37 你好 38 010-3141 39 ‘‘‘ 40 #最常规匹配 41 content=‘Hello 123 456 World_This is a Regex Demo‘ 42 res=re.match(‘Hello\s\d\d\d\s\d{3}\s\w{10}.*Demo‘,content) 43 print(res) 44 print(res.group()) 45 print(res.span()) 46 #泛匹配 47 res=re.match(‘^Hello.*Demo‘,content) 48 print(res.group()) 49 #匹配目标,获得指定数据 50 res=re.match(‘^Hello\s(\d+)\s(\d+)\s.*Demo‘,content) 51 print(res.group()) #取所有匹配的内容 52 print(res.group(1)) #取匹配的第一个括号内的内容 53 print(res.group(2)) #去陪陪的第二个括号内的内容 54 #贪婪匹配:.*代表匹配尽可能多的字符 55 res=re.match(‘^He.*(\d+).*Demo$‘,content) 56 print(res.group(1)) #只打印6,因为.*会尽可能多的匹配,然后后面跟至少一个数字 57 #非贪婪匹配:?匹配尽可能少的字符 58 res=re.match(‘^He.*?(\d+).*Demo$‘,content) 59 print(res.group(1)) #123 60 #匹配模式:.不能匹配换行符 61 content=‘‘‘Hello 123456 World_This 62 is a Regex Demo 63 ‘‘‘ 64 res=re.match(‘He.*?(\d+).*?Demo$‘,content) 65 print(res) #输出None 66 res=re.match(‘He.*?(\d+).*?Demo$‘,content,re.S) #re.S让.可以匹配换行符 67 print(res) 68 print(res.group(1)) 69 #转义:\ 70 content=‘price is $5.00‘ 71 res=re.match(‘price is $5.00‘,content) 72 print(res) #None 73 res=re.match(‘price is \$5\.00‘,content) 74 print(res) #<_sre.SRE_Match object; span=(0, 14), match=‘price is $5.00‘> 75 ‘‘‘ 76 尽量精简,详细的如下: 77 尽量使用泛匹配模式.* 78 尽量使用非贪婪模式:.*? 79 使用括号得到匹配目标:用group(n)去取得结果 80 有换行符就用re.S:修改模式 81 ‘‘‘ 82 #re.search:会扫描整个字符串,不会从头开始,找到第一个匹配的结果就会返回 83 content=‘Extra strings Hello 123 456 World_This is a Regex Demo Extra strings‘ 84 res=re.match(‘Hello.*?(\d+).*?Demo‘,content) 85 print(res) #输出结果为None 86 res=re.search(‘Hello.*?(\d+).*?Demo‘,content) 87 print(res.group(1)) #输出结果为123 88 #re.sub:字符串替换 89 content=‘Extra strings Hello 123 456 World_This is a Regex Demo Extra strings‘ 90 content=re.sub(‘\d+‘,‘‘,content) 91 print(content) 92 #用\1取得第一个括号的内容 93 #用法:将123与456换位置 94 content=‘Extra strings Hello 123 456 World_This is a Regex Demo Extra strings‘ 95 content=re.sub(‘(Extra.*?)(\d+)(\s)(\d+)(.*?strings)‘,r‘\1\4\3\2\5‘,content) 96 print(content) 97 content=re.sub(‘(\d+)(\s)(\d+)‘,r‘\3\2\1‘,content) 98 print(content) 99 res=re.search(‘Extra.*?(\d+).*strings‘,content) 100 print(res.group(1))
匹配语法
12、suprocess模块
subprocess模块是python从2.4版本开始引入的模块。主要用来取代 一些旧的模块方法,如os.system、os.spawn*、os.popen*、commands.*等。subprocess通过子进程来执行外部指令,并通过input/output/error管道,获取子进程的执行的返回信息。
call:执行命令,返回状态码
ret = subprocess.call(["ls", "-l"], shell=False)
ret = subprocess.call("ls -l", shell=True)
check_call:执行命令,如果执行状态码是 0 ,则返回0,否则抛异常
subprocess.check_call(["ls", "-l"])
subprocess.check_call("exit 1", shell=True)
check_output:执行命令,如果状态码是 0 ,则返回执行结果,否则抛异常
subprocess.check_output(["echo", "Hello World!"])
subprocess.check_output("exit 1", shell=True)
subprocess.Popen(...):用于执行复杂的系统命令
参数:
args:shell命令,可以是字符串或者序列类型(如:list,元组)
bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。
所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。
shell:同上
cwd:用于设置子进程的当前目录
env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
universal_newlines:不同系统的换行符不同,True -> 同意使用 \n
startupinfo与createionflags只在windows下有效
将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等
1 import subprocess 2 res1=subprocess.Popen(r‘dir D:\zz\aa\t1‘,shell=True,stdout=subprocess.PIPE) 3 res=subprocess.Popen(‘findstr test*‘,shell=True,stdin=res1.stdout, 4 stdout=subprocess.PIPE) 5 print(res.stdout.read())
13、logging模块
很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,可以通过它存储各种格式的日志,logging的日志可以分为 debug(), info(), warning(), error() , critical() 5个级别
1 CRITICAL = 50 #FATAL = CRITICAL 2 ERROR = 40 3 WARNING = 30 #WARN = WARNING 4 INFO = 20 5 DEBUG = 10 6 NOTSET = 0 #不设置
1 import logging 2 3 logging.debug(‘调试debug‘) 4 logging.info(‘消息info‘) 5 logging.warning(‘警告warn‘) 6 logging.error(‘错误error‘) 7 logging.critical(‘严重critical‘) 8 9 ‘‘‘ 10 WARNING:root:警告warn 11 ERROR:root:错误error 12 CRITICAL:root:严重critical 13 ‘‘‘
简单用法
为logging模块指定全局配置,针对所有logger有效,控制打印到文件中
1 ‘‘‘ 2 可在logging.basicConfig()函数中通过具体参数来更改logging模块默认行为,可用参数有 3 filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。 4 filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。 5 format:指定handler使用的日志显示格式。 6 datefmt:指定日期时间格式。 7 level:设置rootlogger的日志级别 8 stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。 9 format参数中可能用到的格式化串: 10 %(name)s:Logger的名字,并非用户名,详细查看 11 %(levelno)s:数字形式的日志级别 12 %(levelname)s:文本形式的日志级别 13 %(pathname)s:调用日志输出函数的模块的完整路径名,可能没有 14 %(filename)s:调用日志输出函数的模块的文件名 15 %(module)s:调用日志输出函数的模块名 16 %(funcName)s:调用日志输出函数的函数名 17 %(lineno)d:调用日志输出函数的语句所在的代码行 18 %(created)f:当前时间,用UNIX标准的表示时间的浮 点数表示 19 %(relativeCreated)d:输出日志信息时的,自Logger创建以 来的毫秒数 20 %(asctime)s:字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒 21 %(thread)d:线程ID。可能没有 22 %(threadName)s:线程名。可能没有 23 %(process)d:进程ID。可能没有 24 %(message)s:用户输出的消息 25 ‘‘‘ 26 import logging 27 logging.basicConfig(filename=‘example.log‘, 28 format=‘%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s‘, 29 datefmt=‘%Y-%m-%d %H:%M:%S %p‘, 30 level=10) 31 32 logging.debug(‘debug‘) 33 logging.info(‘info‘) 34 logging.warning(‘warn‘) 35 logging.error(‘error‘) 36 logging.critical(‘critical‘) 37 # 输出: 38 ‘‘‘ 39 2018-06-01 20:52:44 PM - root - DEBUG -log模块: debug 40 2018-06-01 20:52:44 PM - root - INFO -log模块: info 41 2018-06-01 20:52:44 PM - root - WARNING -log模块: warn 42 2018-06-01 20:52:44 PM - root - ERROR -log模块: error 43 2018-06-01 20:52:44 PM - root - CRITICAL -log模块: critical 44 2018-06-01 20:53:01 PM - root - DEBUG -log模块: debug 45 2018-06-01 20:53:01 PM - root - INFO -log模块: info 46 2018-06-01 20:53:01 PM - root - WARNING -log模块: warn 47 2018-06-01 20:53:01 PM - root - ERROR -log模块: error 48 2018-06-01 20:53:01 PM - root - CRITICAL -log模块: critical 49 ‘‘‘
Python+logger流示意图
Python 使用logging模块记录日志涉及四个主要类:
logger:产生日志的对象,提供了应用程序可以直接使用的接口;
handler:接收日志然后控制打印到不同的地方,FileHandler用来打印到文件中,StreamHandler用来打印到终端;
filter:过滤日志的对象,提供了细度设备来决定输出哪条日志记录;
formatter:决定日志记录的最终输出格式,可以定制不同的日志格式对象,然后绑定给不同的Handler对象使用,以此来控制不同的Handler的日志格式。
1 import logging 2 ‘‘‘ 3 logger 4 每个程序在输出信息之前都要获得一个Logger。Logger通常对应了程序的模块名,比如聊天工具的图形界面模块可以这样获得它的Logger: 5 LOG=logging.getLogger(”chat.gui”) 6 而核心模块可以这样: 7 LOG=logging.getLogger(”chat.kernel”) 8 Logger.setLevel(lel):指定最低的日志级别,低于lel的级别将被忽略。debug是最低的内置级别,critical为最高 9 Logger.addFilter(filt)、Logger.removeFilter(filt):添加或删除指定的filter 10 Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增加或删除指定的handler 11 Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():可以设置的日志级别 12 ‘‘‘ 13 #1、logger对象:负责产生日志,然后交给Filter过滤,然后交给不同的Handler输出 14 logger=logging.getLogger(__file__) 15 ‘‘‘ 16 handler 17 handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Logger可以把信息输出到文件,还有些 Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handler 18 Handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略 19 Handler.setFormatter():给这个handler选择一个格式 20 Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象 21 22 每个Logger可以附加多个Handler。常用的Handler: 23 1) logging.StreamHandler 24 使用这个Handler可以向类似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息。它的构造函数是: 25 StreamHandler([strm]) 26 其中strm参数是一个文件对象。默认是sys.stderr 27 2) logging.FileHandler 28 和StreamHandler类似,用于向一个文件输出日志信息。不过FileHandler会帮你打开这个文件。它的构造函数是: 29 FileHandler(filename[,mode]) 30 filename是文件名,必须指定一个文件名。 31 mode是文件的打开方式。参见Python内置函数open()的用法。默认是’a‘,即添加到文件末尾。 32 3) logging.handlers.RotatingFileHandler 33 这个Handler类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建 一个新的同名日志文件继续输出。比如日志文件是chat.log。当chat.log达到指定的大小之后,RotatingFileHandler自动把 文件改名为chat.log.1。不过,如果chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。。。最后重新创建 chat.log,继续输出日志信息。它的构造函数是: 34 RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]]) 35 其中filename和mode两个参数和FileHandler一样。 36 maxBytes用于指定日志文件的最大文件大小。如果maxBytes为0,意味着日志文件可以无限大,这时上面描述的重命名过程就不会发生。 37 backupCount用于指定保留的备份文件的个数。比如,如果指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被更名,而是被删除。 38 4) logging.handlers.TimedRotatingFileHandler 39 这个Handler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就 自动创建新的日志文件。重命名的过程与RotatingFileHandler类似,不过新的文件不是附加数字,而是当前时间。它的构造函数是: 40 TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]]) 41 其中filename参数和backupCount参数和RotatingFileHandler具有相同的意义。 42 interval是时间间隔。 43 when参数是一个字符串。表示时间间隔的单位,不区分大小写。它有以下取值: 44 S 秒 45 M 分 46 H 小时 47 D 天 48 W 每星期(interval==0时代表星期一) 49 midnight 每天凌晨 50 ‘‘‘ 51 #2、Handler对象:接收logger传来的日志,然后控制输出 52 h1=logging.FileHandler(‘t1.log‘) #打印到文件 53 h2=logging.FileHandler(‘t2.log‘) #打印到文件 54 h3=logging.StreamHandler() #打印到终端 55 #3、Formatter对象:日志格式 56 formmater1=logging.Formatter(‘%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s‘, 57 datefmt=‘%Y-%m-%d %H:%M:%S %p‘,) 58 formmater2=logging.Formatter(‘%(asctime)s : %(message)s‘, 59 datefmt=‘%Y-%m-%d %H:%M:%S %p‘,) 60 formmater3=logging.Formatter(‘%(name)s %(message)s‘,) 61 #4、为Handler对象绑定格式 62 h1.setFormatter(formmater1) 63 h2.setFormatter(formmater2) 64 h3.setFormatter(formmater3) 65 #5、将Handler添加给logger并设置日志级别 66 logger.addHandler(h1) 67 logger.addHandler(h2) 68 logger.addHandler(h3) 69 logger.setLevel(10) 70 #6、测试 71 logger.debug(‘debug‘) 72 logger.info(‘info‘) 73 logger.warning(‘warning‘) 74 logger.error(‘error‘) 75 logger.critical(‘critical‘)
logger是第一级过滤,然后才能到handler,我们可以给logger和handler同时设置level,Logger是第一个根据级别过滤消息的,如果您将Logger设置为INFO,并将所有处理程序都设置为DEBUG,那么仍然不会接收处理程序上的调试消息,它们将被Logger本身拒绝。如果您将日志记录器设置为DEBUG,而所有处理程序都设置为INFO,那么您也不会收到任何调试消息,因为当日志记录器说“ok, process this”时,处理程序会拒绝它(DEBUG < INFO)。
原文地址:https://www.cnblogs.com/hy0822/p/9085046.html