zoukankan      html  css  js  c++  java
  • python 07 模块

    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)
    View Code
     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))。
    View Code

    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
    View Code

    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)
    View Code 
     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模块dirname1dirname2')  #  可生成多层递归目录
     7 os.removedirs('D:zz模块dirname1dirname2') #   若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
     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下为"
    ",Linux下为"
    "
    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的大小
    View Code
     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]
    View Code

    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 两个模块来进行的
    View Code

    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))
    View Code

    一个软件/程序的执行就是在处理一系列状态的变化,在编程语言中,'状态'会以各种各样有结构的数据类型(也可简单的理解为变量)的形式被保存在内存中。内存是无法永久保存数据的,当程序运行了一段时间,我们断电或者重启程序,内存中关于这个程序的之前一段时间的数据(有结构)都被清空了。在断电或重启程序之前将程序当前内存中所有的数据都保存下来(保存到文件中),以便于下次程序执行能够从文件中载入之前的数据,然后继续执行,这就是序列化。序列化之后,不仅可以把序列化后的内容写入磁盘,还可以通过网络传输到别的机器上,如果收发的双方约定好使用一种序列化的格式,那么便打破了平台/语言差异化带来的限制,实现了跨平台数据交互。

    序列化:我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化。在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()
    View Code

    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>
    View Code
     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 '''
    View Code

    对加密算法中添加自定义key再来做加密:

    1 import hashlib
    2 hash = hashlib.md5('abcd'.encode('utf8'))
    3 hash.update('zz'.encode('utf8'))
    4 print (hash.hexdigest())#363110069610b4595ebb1596dd172517
    View Code
     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 匹配任意空白字符,等价于 [ f].
    S 匹配任意非空字符
    匹配一个换行符
    匹配一个制表符
    d 匹配任意数字,等价于 [0-9]
    D 匹配任意非数字
    A 匹配字符串开始
     匹配字符串结束
    ^ 匹配字符串的开头
    $ 匹配字符串的末尾
    . 匹配任意字符,除了换行符,当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:匹配任意空白字符,等价于 [	
    
    f]
      9 #S:匹配任意非空字符
     10 print(re.findall('s','runoob 123 google 456')) #[' ', ' ', ' ']
     11 print(re.findall('s','runoob 
     123 	 google')) #[' ', '
    ', ' ', ' ', '	', ' ']  #
     	都是空,都可以被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 #
    :匹配一个换行符
     15 #	:匹配一个制表符
     16 print(re.findall(r'
    ','hello egon 
    123')) #['
    ']
     17 print(re.findall(r'	','hello egon	123')) #['	']
     18 
     19 #d:匹配任意数字,等价于 [0-9]
     20 #D:匹配任意非数字
     21 print(re.findall('d','hello egon 123')) #['1', '2', '3']
     22 print(re.findall('D','hello 
     egon 123')) #['h', 'e', 'l', 'l', 'o', ' ', '
    ', ' ', 'e', 'g', 'o', 'n', ' ']
     23 
     24 #A:匹配字符串开始
     25 #:匹配字符串结束
     26 print(re.findall('Ahe','hello egon 123')) #['he'],A==>^
     27 print(re.findall('123','hello egon 123')) #['he'],==>$
     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
    b')) #[]
     39 print(re.findall('a.b','a
    b',re.S)) #['a
    b']
     40 print(re.findall('a.b','a
    b',re.DOTALL)) #['a
    b']同上一条意思一样
     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','ac')) #对于正则来说a\c确实可以匹配到ac,但是在python解释器读取a\c时,会发生转义,然后交给re去执行,所以抛出异常
     99 print(re.findall(r'a\c','ac')) #r代表告诉解释器使用rawstring,即原生字符串,把我们正则内的所有符号都当普通字符处理,不要转义
    100 print(re.findall('a\\c','ac')) #同上面的意思一样,和上面的结果一样都是['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'52341','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 egon@oldboyedu.com
     37 你好
     38 010-3141
     39 '''
     40 #最常规匹配
     41 content='Hello 123 456 World_This is a Regex Demo'
     42 res=re.match('Hellosdddsd{3}sw{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('^Hellos(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'14325',content)
     96 print(content)
     97 content=re.sub('(d+)(s)(d+)',r'321',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 -> 同意使用
    startupinfo与createionflags只在windows下有效
    将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等

    1 import subprocess
    2 res1=subprocess.Popen(r'dir D:zzaa	1',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())
    View Code

    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 #不设置
    View Code
     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 '''
    View Code

    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')
    View Code

    logger是第一级过滤,然后才能到handler,我们可以给logger和handler同时设置level,Logger是第一个根据级别过滤消息的,如果您将Logger设置为INFO,并将所有处理程序都设置为DEBUG,那么仍然不会接收处理程序上的调试消息,它们将被Logger本身拒绝。如果您将日志记录器设置为DEBUG,而所有处理程序都设置为INFO,那么您也不会收到任何调试消息,因为当日志记录器说“ok, process this”时,处理程序会拒绝它(DEBUG < INFO)。

  • 相关阅读:
    安卓 出现Cannot launch AVD in emulator 错误
    服务器架构中,集群,负载均衡,分布式有什么区别吗
    JavaScript事件
    替换节点内文本的万用函数
    DOM(Document Object Module,文档对象模型)为JavaScript提供完整,全面控制网页结构与内容的对象
    c++和java的区别
    解决Spark集群无法停止
    spark 作业调度
    hadoop,hbase,hive,zookeeper整合可行性分析及版本确定
    hadoop+spark+kudu
  • 原文地址:https://www.cnblogs.com/hy0822/p/9085046.html
Copyright © 2011-2022 走看看