python学习-常用模块:logging,shelve,xml,configparser,hashlib

'''
logging 模块
    为logging模块指定全局配置,针对所有logger有效,控制打印到文件中
    
    logging.basicConfig():更改logging模块默认行为,可用参数有:
        filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
        filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
        format:指定handler使用的日志显示格式。 
        datefmt:指定日期时间格式。 
        level:设置rootlogger(后边会讲解具体概念)的日志级别 
        stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。
                若同时列出了filename和stream两个参数,则stream参数会被忽略。即:不可同时输出终端和写入文件
    
    format参数中可能用到的格式化串:
        %(name)s Logger的名字
        %(levelno)s 数字形式的日志级别
        %(levelname)s 文本形式的日志级别
        %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
        %(filename)s 调用日志输出函数的模块的文件名
        %(module)s 调用日志输出函数的模块名
        %(funcName)s 调用日志输出函数的函数名
        %(lineno)d 调用日志输出函数的语句所在的代码行
        %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
        %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
        %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
        %(thread)d 线程ID。可能没有
        %(threadName)s 线程名。可能没有
        %(process)d 进程ID。可能没有
        %(message)s用户输出的消息

'''
# import logging
#
# # 指定日志写入格式和级别,不可同时操作 终端打印和文件写入 操作
# logging.basicConfig(filename='access.log',
#                     format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
#                     datefmt='%Y-%m-%d %H:%M:%S %p',
#                     level=10)
#
# # 用来产生不同类型的日志,严重级别从小到大
# logging.debug('debug日志') #10
# logging.info('info日志') #20
# logging.warning('warning日志') #30
# logging.error('error日志') #40
# logging.critical('critical日志') #50

'''
 logging模块中的 Formatter,Handler,Logger,Filter 对象
 
    logger 对象:负责产生各种级别的日志
    filter 对象:负责过滤日志的对象
    Handler 对象:接收日志然后控制打印到不同的地方
                  FileHandler用来打印到文件中,StreamHandler用来打印到终端
    Formatter 对象:可以定制不同的日志格式对象
                    然后绑定给不同的Handler对象使用,以此来控制不同的Handler的日志格式
'''

# import logging
#
# # logger对象产生日志
# logger = logging.getLogger('用户交易')  # 日志名用来标识日志绑定的相关用户
#
# # filter对象过滤日志
#
# # handler对象控制日志输出位置
# fh1 = logging.FileHandler('a1.log',encoding='utf-8')  # 打印到文件
# fh2 = logging.FileHandler('a2.log',encoding='utf-8')  # 打印到文件
# ch = logging.StreamHandler()  # 打印到终端
#
# # formatter对象定制handler日志格式
# formmater1=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
#                     datefmt='%Y-%m-%d %H:%M:%S %p',)
# formmater2=logging.Formatter('%(asctime)s :  %(message)s',
#                     datefmt='%Y-%m-%d %H:%M:%S %p',)
# formmater3=logging.Formatter('%(name)s %(message)s',)
#
# # 绑定logger对象和handler对象
# logger.addHandler(fh1)
# logger.addHandler(fh2)
# logger.addHandler(ch)
#
# # 绑定handler对象和formatter对象
# fh1.setFormatter(formmater1)
# fh2.setFormatter(formmater2)
# ch.setFormatter(formmater3)
#
# # 设置日志级别。有logger对象和handler对象两层关卡,必须都满足级别及以上级别,最终日志才会放行,通常二者级别相同
# logger.setLevel(10)
#
# fh1.setLevel(10)
# fh2.setLevel(10)
# ch.setLevel(10)
#
# # 使用logger对象产生日志
# logger.debug('debug')
# logger.info('info')
# logger.warning('warning')
# logger.error('error')
# logger.critical('critical')
# *--------------------------------------
# logging模块的使用模板
# log配置字典
# 定义三种日志输出格式 开始
# import os
# import logging.config
# standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
#                   '[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字
#
# simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
#
# id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
#
# # 定义日志输出格式 结束
# logfile_dir = os.path.dirname(os.path.abspath(__file__))  # log文件的目录
#
# logfile_name = 'all2.log'  # log文件名
#
# logfile_path = os.path.join(logfile_dir, logfile_name)
#
#
# LOGGING_DIC = {
#     'version': 1,
#     'disable_existing_loggers': False,
#     'formatters': {
#         'standard': {
#             'format': standard_format
#         },
#         'simple': {
#             'format': simple_format
#         },
#     },
#     'filters': {},
#     'handlers': {
#         #打印到终端的日志
#         'console': {
#             'level': 'DEBUG',
#             'class': 'logging.StreamHandler',  # 打印到屏幕
#             'formatter': 'simple'
#         },
#         #打印到文件的日志,收集info及以上的日志
#         'default': {
#             'level': 'DEBUG',
#             'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
#             'formatter': 'standard',
#             'filename': logfile_path,  # 日志文件
#             'maxBytes': 1024*1024*5,  # 日志大小 5M
#             'backupCount': 5,
#             'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
#         },
#     },
#     'loggers': {
#         '': {           #空key用来保证任意名字取到的值都是默认格式
#             'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
#             'level': 'DEBUG',
#         },
#     },
# }
# def load_my_logging_cfg():
#     logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
#     logger = logging.getLogger(__name__)  # 生成一个log实例
#     logger.info('It works!')  # 记录该文件的运行状态
#
# if __name__ == '__main__':
#     load_my_logging_cfg()

# ----------------------------------------
'''
shelve 模块 :一种pthon自带的序列化工具,可自动序列化
            可以直接通过import shelve来引用。
            shelve类似于一个存储持久化对象的持久化字典,即字典文件。
            使用方法也类似于字典。
        使用方法:
            1.open
            2.读写
            3.close
    注意: shelve 模块只有一个open函数,返回类似字典的对象,可读可写;
            key必须为字符串,而值可以是python所支持的数据类型
'''

# import shelve
#
# # 保存对象至shelve文件中(序列化):
# db = shelve.open('shelveDict')  # 打开一个文件
# db['wangzhe'] = 'wangzhe' # 向文件中添加内容,添加方式与给字典添加键值对相同
# db['lijianguo'] = 'lijianguo'
# db.close()   #关闭文件
#
# # 从文件中读取对象(反序列化):
# import shelve
# db = shelve.open('shelveDict')  #打开文件
# a = db.get('wangzhe')
# print(db['wangzhe'])   #向从字典中获取键的方式一样读取内容
# print(db['lijianguo'])  #结果为{'age': 25, 'name': 'lijianguo'}
# db.close()  #关闭文件
#
# # 更新文件中的数据:
# import shelve
# db = shelve.open('shelveDict')  #打开文件
# wangzhe = db['wangzhe']     #从文件中读取之前存储的对象
# wangzhe['name'] = 'wang zhe'   #直接对对象进行修改
# db['wangzhe'] = wangzhe     #重新存储至字典文件对象中
# print(db['wangzhe'] )    #结果如下{'age': 24, 'name': 'wang zhe'}
# db.close()   #关闭文件

'''
xml模块:
    xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单。
语法:
    一、任何的起始标签都必须有一个结束标签。
    
    二、可以采用另一种简化语法,可以在一个标签中同时表示起始和结束标签。
        这种语法是在大于符号之前紧跟一个斜线(/),例如<百度百科词条/>。
        XML解析器会将其翻译成<百度百科词条></百度百科词条>。
        
    三、标签必须按合适的顺序进行嵌套,所以结束标签必须按镜像顺序匹配起始标签,
        例如<tag1>
                <tag2>
                </tag2>
            </tag1>
        这好比是将起始和结束标签看作是数学中的左右括号:
            在没有关闭所有的内部括号之前,是不能关闭外面的括号的。
            
    四、所有的特性都必须有值。即:特性指的是属性
    
    五、所有的特性都必须在值的周围加上双引号。

使用场景:
    1.配置文件
    2.常规的数据交换

与json的区别:
    xml的优点:
        (1)格式统一
        (2)容易与其他系统进行远程交互,数据共享比较方便
    xml的缺点:
        (1)xml文件庞大,文件格式复杂,传输占带宽
        (2)服务器和客户端都需要花费大量代码来解析xml,导致服务器和客户端代码变得异常复杂且不易维护
        (3)客户端和服务端解析xml花费较多的资源和时间
    json的优点:
        (1)数据格式比较简单,易于读写,格式是压缩的,占用带宽小
        (2)易于解析,包括JavaScript可以通过简单的通过eval_r()进行json数据的读取
    json的缺点:
        (1)没有xml那么通用
        (2)json格式目前还在推广阶段
        
ElmentTree 表示文件的节点树   
Elment 表示一个节点:
    属性:
        1.text : <>text</>
        2.attrib : 所有属性
        3.tag: 标签的名字
    方法:
        get 获取某个属性的值
'''

# import xml.etree.ElementTree as et

# 获取节点树
# tree = et.parse('TEST.xml') #读取xml到内存,的到一个包含所有数据的节点树
# print(tree)

# 查找标签
# root = tree.getroot()# 获取根标签
# print(root.iter('year')) #全文搜索,返回迭代器对象
# print(root.find('country')) #在root的子节点找,只找一个,且只找第一个
# print(root.findall('country')) #在root的子节点找,找所有

# 遍历xml文件
# for country in root:
#     print(country.tag,country.attrib,country.text)
#     for t in country:
#         print(t.tag,t.attrib,t.text)

#获取一个属性
# print(root.find('country').get('name'))
#

# 修改xml文件
# 读取到内存 并在内存中修改
# tree = et.parse('TEST.xml')
# for country in tree.findall('country'):
#     yeartag = country.find('year')
#     yeartag.text = str(int(yeartag.text) + 1)
# # 写回文件
# tree.write('TEST.xml',encoding='utf-8',xml_declaration=False)
#

# for node in root.iter('year'):
#     new_year = int(node.text) + 1
#     node.text = str(new_year)
#     node.set('updated', 'yes')
#     node.set('version', '1.0')
# tree.write('test.xml')

# 删除
# tree = et.parse('TEST.xml')
# root = tree.getroot()
# for country in root.findall('country'):
#     rank = int(country.find('rank').text)
#     if rank > 50:
#         root.remove(country)
# tree.write('output.xml')

# 增加xml文件
#在country内添加(append)节点year2
# import xml.etree.ElementTree as ET
# tree = ET.parse("a.xml")
# root=tree.getroot()
# for country in root.findall('country'):
#     for year in country.findall('year'):
#         if int(year.text) > 2000:
#             year2=ET.Element('year2')
#             year2.text='新年'
#             year2.attrib={'update':'yes'}
#             country.append(year2) #往country节点下添加子节点
# tree.write('a.xml.swap')

# 创建xml文档

# 方法一:
# import xml.etree.ElementTree as ET
# # 创建根标签
# new_xml = ET.Element("namelist")
# #简单创建xml
# # name = ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"})
# # age = ET.SubElement(name, "age", attrib={"checked": "no"})
# # sex = ET.SubElement(name, "sex")
# # sex.text = '33'
# # name2 = ET.SubElement(new_xml, "name", attrib={"enrolled": "no"})
# # age = ET.SubElement(name2, "age")
# # age.text = '19'
# # # 写入文件
# et = ET.ElementTree(new_xml) #生成文档对象
# et.write("test1.xml", encoding="utf-8", xml_declaration=True)
# ET.dump(new_xml)  # 打印生成的格式

# 方法二:
# import xml.etree.ElementTree as ET
# new_xml = ET.Element("namelist")
# # 创建节点树 et
# et = ET.ElementTree(new_xml)  # 生成文档对象
# person = ET.Element('person')
# person.attrib['name'] = 'test'
# person.attrib['sex'] = 'male'
# person.attrib['age'] = '18'
# person.attrib['text'] = '这是一个person标签'
# new_xml.append(person)
# # # 写入文件
# et.write("test1.xml", encoding="utf-8", xml_declaration=True)
# ET.dump(new_xml)  # 打印生成的格式

'''
configparser 模块 :配置文件解析模块,解析配置文件(.ini .cfg)

    配置文件格式:
        1.section 分区
        2.option 选项
    注:一个文件可以有多个section,一个section可以有多个选项
        例如:
            # 注释1
            ; 注释2
            
            [section1]
            
            # 每一行作为一个 option 
            k1 = v1
            k2:v2
            user=egon
            age=18
            is_admin=true
            salary=31
            
            [section2]
            k1 = v1
            ……
'''
# import configparser
#
# # 打开配置文件,创建配置文件对象
# cfg = configparser.ConfigParser()
# # 读取一个配置文件
# cfg.read('download.ini',)
#
#
# # 查询操作:
#
# #查看所有的分区名
# res=cfg.sections() #['section1', 'section2']
# print(res)
# # 获取指定section名下的所有option名
# print(cfg.options('section1'))
# #查看指定section下的某一个已知option的值
# print(cfg.get('section1','maxSpeed'))#返回字符串
# print(cfg.getint('section1','maxSpeed'))#返回整形
# print(cfg.getfloat('section1','maxSpeed'))#返回浮点
# # print(cfg.getboolean('section1','maxSpeed'))#返回布尔
#
# #查看标题section1下所有key=value的key
# options=cfg.options('section1')
# print(options)
# #['k1', 'k2', 'user', 'age', 'is_admin', 'salary'
#
# #查看标题section1下所有key=value的(key,value)格式
# item_list=cfg.items('section1')
# print(item_list)
# #[('k1', 'v1'), ('k2', 'v2'), ('user', 'egon'), ('age', '18'), ('is_admin', 'true'), ('salary', '31')]
#
#
# # 修改配置文件内容
#
# #删除整个section2分区
# cfg.remove_section('section2')
# #删除分区section1下的某个option(k1和k2)
# cfg.remove_option('section1','k1')
# cfg.remove_option('section1','k2')
# #判断是否存在某个section
# print(cfg.has_section('section1'))
# #判断标题section1下是否有user
# print(cfg.has_option('section1',''))
# #添加一个section
# cfg.add_section('egon')
# #在标题egon下添加name=egon,age=18的配置
# # cfg.set(section名,option名,option值)
# cfg.set('egon','name','egon')
# cfg.set('egon','age','18') #报错,必须是字符串
#
# #最后将修改的内容写入文件,完成最终的修改
# cfg.write(open('download.ini','w'))

# -----------------------
# # 添加一个ini配置文件
# import configparser
#
# # 打开文件,创建一个配置文件对象
# config = configparser.ConfigParser()
# # 设置文件内属性
# # default section创建
# config["DEFAULT"] = {'ServerAliveInterval': '45',
#                      'Compression': 'yes',
#                      'CompressionLevel': '9'}
#
# config['bitbucket.org'] = {}
# # bitbucket.org 分区下的User option进行赋值
# config['bitbucket.org']['User'] = 'hg'
#
# config['topsecret.server.com'] = {}
# # 分步对topsecret.server.com分区下的option进行赋值
# topsecret = config['topsecret.server.com']
# topsecret['Host Port'] = '50022'
# topsecret['ForwardX11'] = 'no'
# config['DEFAULT']['ForwardX11'] = 'yes'
#
# # 写入文件
# with open('example.ini', 'w') as configfile:
#     config.write(configfile)

'''
hashlib模块
     1、什么叫hash:     hash是一种算法
        (3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法)
            该算法接受传入的内容,经过运算得到一串hash值
     2、hash值的特点是:
        2.1 只要传入的内容一样,得到的hash值必然一样;输入内容不同,的到的hash值可能相同
            =====>要用明文传输密码文件完整性校验
        2.2 不能由hash值返解成内容
            =======》把密码做成hash值,不应该在网络传输明文密码
        2.3 只要使用的hash算法不变,无论校验的内容有多大,得到的hash值长度是固定的
    
    用处:将其用于加密和文件校验
'''
# import hashlib
#
# m = hashlib.md5()  # m=hashlib.sha256()
#
# m.update('hello'.encode('utf8'))
# print(m.hexdigest())  # 5d41402abc4b2a76b9719d911017c592
#
# m.update('alvin'.encode('utf8'))
# print(m.hexdigest())  # 92a7e713c30abbb0319fa07da2a5c4af
#
# m2 = hashlib.md5()
# m2.update('helloalvin'.encode('utf8'))
# print(m2.hexdigest())  # 92a7e713c30abbb0319fa07da2a5c4af
#
# '''
# 注意:把一段很长的数据update多次,与一次update这段长数据,得到的结果一样
# 但是update多次为校验大文件提供了可能。
# '''
#
# #
# # python 还有一个 hmac 模块,
# # 它内部对我们创建 key 和 内容 进行进一步的处理然后再加密:
# import hmac
# h = hmac.new('alvin'.encode('utf8'))
# h.update('hello'.encode('utf8'))
# print (h.hexdigest())#320df9832eab4c038b6c1d7ed73a5940

猜你喜欢

转载自blog.csdn.net/qq_33961117/article/details/81627984