第九章 常用模块(续)
1.序列化模塊? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
1.1 什么叫序列化
例:有一個(gè)班級(jí)信息字典{'10010000':{'name':'zhangsan', 'age':22, 'class':'python21'},...},在程序結(jié)束后需要保存,而在python中只有字符串能保存到文件中。再次使用字典的時(shí)候,可以使用eval轉(zhuǎn)化,但是非常不安全,所以引入了序列化
序列化就是 數(shù)據(jù)類型轉(zhuǎn)化成字符串的過(guò)程 -- 數(shù)據(jù)類型 --> 字符串的過(guò)程
字符串化也叫做序列化
1.2 為什么要用序列化呢?(固態(tài)存儲(chǔ)、網(wǎng)絡(luò)傳輸)
數(shù)據(jù)從內(nèi)存到文件
數(shù)據(jù)在網(wǎng)絡(luò)上傳輸,在網(wǎng)線上能夠傳遞的只有 010101 -- 字節(jié) -- 字符串 -- 字典
1.3 python中的序列化模塊都有哪些?
json 通用的 支持的數(shù)據(jù)類型 list tuple dict
pickle 在python中通用的 支持幾乎所有python中的數(shù)據(jù)類型
shelve 在py3種不是很好用,在python中使用的便捷的序列化工具
2.json模塊? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
基于內(nèi)存的操作
import json dic = {'k': 'v'} # 基于內(nèi)存的操作(和內(nèi)存交互的) print(type(dic)) # <class 'dict'> json_dic = json.dumps(dic) # 所有引號(hào)都會(huì)變成雙引號(hào)字典 轉(zhuǎn)化成字符串的過(guò)程 -- 序列化 print(json_dic) # {"k": "v"} print(dic) # {'k': 'v'} print(type(json_dic)) # <class 'str'> print(json.loads(json_dic)) # 字符串 轉(zhuǎn)回其他數(shù)據(jù)類型的過(guò)程 -- 反序列化 # {'k': 'v'}基于文件的操作
# 基于文件的操作 import json dic = {'k': 'v'} # 寫入文件 with open('d', 'w') as f:json.dump(dic, f) #dump是和文件交互的# 查看文件 with open('d') as f:print(json.load(f)) # 從文件中反序列化 # {'k': 'v'}# 如果要dump多條數(shù)據(jù) # 每一條數(shù)據(jù)dumps一下 編輯成字符串,然后打開(kāi)文件 write寫進(jìn)文件里 \n # 讀取的時(shí)候按照標(biāo)志讀取或者按行讀 # 讀出來(lái)之后 在使用loads with open('aaa', 'w') as f:str_dic = json.dumps(dic)f.write(str_dic + '\n')f.write(str_dic + '\n')f.write(str_dic + '\n')f.write(str_dic + '\n') # cat aaa # {"k": "v"} # {"k": "v"} # {"k": "v"} # {"k": "v"} with open('aaa') as f:for line in f:print(json.loads(line.strip())) # {'k': 'v'} # {'k': 'v'} # {'k': 'v'} # {'k': 'v'}3.pickle模塊? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
pickle模塊的基本用法很json模塊相同
import pickle # pickle看不到轉(zhuǎn)碼后的內(nèi)容 class A:def __init__(self, name):self.name = namealex = A('alex') # json.dumps(alex) # 支持的數(shù)據(jù)類型有限 # TypeError: Object of type 'A' is not JSON serializable print(pickle.dumps(alex)) # b'\x80\x03c__main__\nA\nq\x00)\x81q\x01}q\x02X\x04\x00\x00\x00nameq\x03X\x04\x00\x00\x00alexq\x04sb.'基于文件的操作
pickle模塊相對(duì)json模塊的優(yōu)勢(shì)一:支持幾乎所有python中的數(shù)據(jù)類型
with open('bbb', 'wb') as f:pickle.dump(alex, f)with open('bbb', 'rb') as f:print(pickle.load(f)) # <__main__.A object at 0x00000159473C5940> with open('bbb', 'rb') as f:obj = pickle.load(f)print(obj.name) # alexpickle模塊相對(duì)json模塊的優(yōu)勢(shì)二:多次load內(nèi)容比較簡(jiǎn)單
# 多次寫入文件 with open('bbb', 'wb') as f:pickle.dump(alex, f)pickle.dump(alex, f)pickle.dump(alex, f)pickle.dump(alex, f)# 多次讀取內(nèi)容 with open('bbb', 'rb') as f:try:while True:obj = pickle.load(f)print(obj.name)except EOFError:pass # alex # alex # alex # alex總結(jié):
1.pickle支持更多的數(shù)據(jù)類型
2.pickle的結(jié)果是二進(jìn)制
3.pickle在和文件交互的時(shí)候可以被多次load
4.hashlib摘要算法模塊? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Python的hashlib提供了常見(jiàn)的摘要算法,如MD5,SHA1等等。
什么是摘要算法呢?摘要算法又稱哈希算法、散列算法。它通過(guò)一個(gè)函數(shù),把任意長(zhǎng)度的數(shù)據(jù)轉(zhuǎn)換為一個(gè)長(zhǎng)度固定的數(shù)據(jù)串(通常用16進(jìn)制的字符串表示)。
摘要算法就是通過(guò)摘要函數(shù)f()對(duì)任意長(zhǎng)度的數(shù)據(jù)data計(jì)算出固定長(zhǎng)度的摘要digest,目的是為了發(fā)現(xiàn)原始數(shù)據(jù)是否被人篡改過(guò)。
摘要算法之所以能指出數(shù)據(jù)是否被篡改過(guò),就是因?yàn)檎瘮?shù)是一個(gè)單向函數(shù),計(jì)算f(data)很容易,但通過(guò)digest反推data卻非常困難。而且,對(duì)原始數(shù)據(jù)做一個(gè)bit的修改,都會(huì)導(dǎo)致計(jì)算出的摘要完全不同。
最常使用的兩種算法sha/md5
4.1 使用hashlib模塊獲取字符串的MD5值
import hashlib# 例:使用hashlib模塊獲取字符串的md5值 md5obj = hashlib.md5() # 實(shí)例化一個(gè)MD5摘要算法的對(duì)象 md5obj.update('alex3714'.encode('utf-8')) # 使用md5算法的對(duì)象來(lái)操作字符串(bytes類型) ret = md5obj.hexdigest() ## 獲取算法的結(jié)果 hex + digest 16進(jìn)制+消化 print(ret, type(ret), len(ret)) # aee949757a2e698417463d47acac93df <class 'str'> 32
4.2?使用hashlib模塊獲取字符串的sha值
# sha算法,后面的數(shù)字越大,結(jié)果越長(zhǎng) md5obj = hashlib.sha256() # 實(shí)例化一個(gè)sha摘要算法的對(duì)象 md5obj.update('alex3714'.encode('utf-8')) # 使用sha算法的對(duì)象來(lái)操作字符串(bytes類型) ret = md5obj.hexdigest() ## 獲取算法的結(jié)果 hex + digest 16進(jìn)制+消化 print(ret, type(ret), len(ret)) #sha1 8a003668a9c990f15148f9e4046e1410781533b6 <class 'str'> 40 #sha256 1e1c67170a2136ba7e18ffee2461fdbcdcf0884d9d9d005d4ab8c8733a15f8ab <class 'str'> 644.3 高級(jí)用法 -- 加鹽
# 例:使用md5算法進(jìn)行加密認(rèn)證 md5obj = hashlib.md5('tesla'.encode('utf-8')) # 加鹽過(guò)程 md5obj.update('alex3714'.encode('utf-8')) # 使用md5算法的對(duì)象來(lái)操作字符串(bytes類型) ret = md5obj.hexdigest() ## 獲取算法的結(jié)果 hex + digest 16進(jìn)制+消化 print(ret, type(ret), len(ret)) # aee949757a2e698417463d47acac93df <class 'str'> 32 # 加鹽前 # 7dafaec086d0ddae18b63e4fffafbf8e <class 'str'> 32 # 加鹽后動(dòng)態(tài)加鹽
# 動(dòng)態(tài)加鹽 -- 有些網(wǎng)站,一旦注冊(cè)了,用戶名就不能更改了,原因是用戶名當(dāng)鹽 username = 'alex' md5obj = hashlib.md5(username.encode('utf-8')) # 加鹽過(guò)程 md5obj.update('alex3714'.encode('utf-8')) # 使用md5算法的對(duì)象來(lái)操作字符串(bits類型) ret = md5obj.hexdigest() ## 獲取算法的結(jié)果 hex + digest 16進(jìn)制+消化 print(ret, type(ret), len(ret)) # ee838c58e5bb3c9e687065edd0ec454f <class 'str'> 324.4 校驗(yàn)文件的一致性
# 校驗(yàn)文件的一致性 # 自動(dòng)化 -- python代碼來(lái)做驗(yàn)證 md5obj = hashlib.md5() # 實(shí)例化一個(gè)MD5摘要算法的對(duì)象 md5obj.update('alex3714'.encode('utf-8')) #使用md5算法的對(duì)象來(lái)操作字符串(bytes類型) print(md5obj.hexdigest()) # aee949757a2e698417463d47acac93dfmd5obj = hashlib.md5() md5obj.update('alex'.encode('utf-8')) md5obj.update('3714'.encode('utf-8')) #使用md5算法的對(duì)象來(lái)操作字符串(bytes類型) print(md5obj.hexdigest()) # aee949757a2e698417463d47acac93df # 說(shuō)明:分多次對(duì)同一個(gè)字符串進(jìn)行摘要和一次性對(duì)這個(gè)字符串的摘要的結(jié)果是相同的
5.configparser模塊 -- ini配置文件? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
該模塊適用于配置文件的格式與windows ini文件類似,可以包含一個(gè)或多個(gè)節(jié)(section),每個(gè)節(jié)可以有多個(gè)參數(shù)(鍵=值)。
5.1 配置文件格式
[DEFAULT] ServerAliveInterval = 45 Compression = yes CompressionLevel = 9 ForwardX11 = yes[bitbucket.org] User = hg[topsecret.server.com] Port = 50022 ForwardX11 = no?5.2 寫入文件范例
import configparser# 實(shí)例化config對(duì)象 config = configparser.ConfigParser()# 給config添加內(nèi)容 # []內(nèi)為配置文件內(nèi)的組名 # 后面的字典為組內(nèi)配置的鍵值對(duì) config["DEFAULT"] = {'ServerAliveInterval': '45','Compression': 'yes','CompressionLevel': '9','ForwardX11':'yes'}config['bitbucket.org'] = {'User':'hg'}config['topsecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'}with open('example.ini', 'w') as configfile:# 使用config的方法將相應(yīng)配置,寫入文件config.write(configfile)5.3 查找文件
import configparserconfig = configparser.ConfigParser()#---------------------------查找文件內(nèi)容,基于字典的形式print(config.sections()) # [] config.read('example.ini')print(config.sections()) # ['bitbucket.org', 'topsecret.server.com']print('bytebong.com' in config) # False print('bitbucket.org' in config) # Trueprint(config['bitbucket.org']["user"]) # hgprint(config['DEFAULT']['Compression']) #yesprint(config['topsecret.server.com']['ForwardX11']) #noprint(config['bitbucket.org']) #<Section: bitbucket.org>for key in config['bitbucket.org']: # 注意,有default會(huì)默認(rèn)default的鍵print(key)print(config.options('bitbucket.org')) # 同for循環(huán),找到'bitbucket.org'下所有鍵print(config.items('bitbucket.org')) #找到'bitbucket.org'下所有鍵值對(duì)print(config.get('bitbucket.org','compression')) # yes get方法Section下的key對(duì)應(yīng)的value5.4 增刪改操作
import configparserconfig = configparser.ConfigParser()config.read('example.ini')config.add_section('yuan')config.remove_section('bitbucket.org') config.remove_option('topsecret.server.com',"forwardx11")config.set('topsecret.server.com','k1','11111') config.set('yuan','k2','22222')config.write(open('new2.ini', "w"))7.logging模塊? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
7.1 默認(rèn)情況下Python的logging模塊將日志打印到了標(biāo)準(zhǔn)輸出中,且只顯示了大于等于WARNING級(jí)別的日志,這說(shuō)明默認(rèn)的日志級(jí)別設(shè)置為WARNING(日志級(jí)別等級(jí)CRITICAL > ERROR > WARNING > INFO > DEBUG),默認(rèn)的日志格式為日志級(jí)別:Logger名稱:用戶輸出消息。
日志級(jí)別
logging.debug('debug message') # 非常細(xì)節(jié)的日志 -- 排查錯(cuò)誤的時(shí)候使用 # DEBUG:root:debug message logging.info('info message') # 正常的日志信息 # INFO:root:info message logging.warning('warning message') # 警告,出現(xiàn)錯(cuò)誤,但是程序可以正常運(yùn)行 # WARNING:root:warning message logging.error('error message') # 錯(cuò)誤 # ERROR:root:error message logging.critical('critical message') # 嚴(yán)重錯(cuò)誤,程序只能重啟才能正常運(yùn)行 # CRITICAL:root:critical message7.2 格式化輸出
靈活配置日志級(jí)別,日志格式,輸出位置
logging.basicConfig()函數(shù)中可通過(guò)具體參數(shù)來(lái)更改logging模塊默認(rèn)行為,可用參數(shù)有:filename:用指定的文件名創(chuàng)建FiledHandler,這樣日志會(huì)被存儲(chǔ)在指定的文件中。 filemode:文件打開(kāi)方式,在指定了filename時(shí)使用這個(gè)參數(shù),默認(rèn)值為“a”還可指定為“w”。 format:指定handler使用的日志顯示格式。 datefmt:指定日期時(shí)間格式。 level:設(shè)置rootlogger(后邊會(huì)講解具體概念)的日志級(jí)別 stream:用指定的stream創(chuàng)建StreamHandler。可以指定輸出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默認(rèn)為sys.stderr。若同時(shí)列出了filename和stream兩個(gè)參數(shù),則stream參數(shù)會(huì)被忽略。format參數(shù)中可能用到的格式化串: %(name)s Logger的名字 %(levelno)s 數(shù)字形式的日志級(jí)別 %(levelname)s 文本形式的日志級(jí)別 %(pathname)s 調(diào)用日志輸出函數(shù)的模塊的完整路徑名,可能沒(méi)有 %(filename)s 調(diào)用日志輸出函數(shù)的模塊的文件名 %(module)s 調(diào)用日志輸出函數(shù)的模塊名 %(funcName)s 調(diào)用日志輸出函數(shù)的函數(shù)名 %(lineno)d 調(diào)用日志輸出函數(shù)的語(yǔ)句所在的代碼行 %(created)f 當(dāng)前時(shí)間,用UNIX標(biāo)準(zhǔn)的表示時(shí)間的浮 點(diǎn)數(shù)表示 %(relativeCreated)d 輸出日志信息時(shí)的,自Logger創(chuàng)建以 來(lái)的毫秒數(shù) %(asctime)s 字符串形式的當(dāng)前時(shí)間。默認(rèn)格式是 “2003-07-08 16:49:45,896”。逗號(hào)后面的是毫秒 %(thread)d 線程ID。可能沒(méi)有 %(threadName)s 線程名。可能沒(méi)有 %(process)d 進(jìn)程ID。可能沒(méi)有 %(message)s用戶輸出的消息format添加格式
# 靈活配置日志級(jí)別,日志格式,輸出位置: # format添加格式 logging.basicConfig(level=logging.DEBUG,format=('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')) # 默認(rèn)包含warning及以上的信息 logging.debug('debug message') # 非常細(xì)節(jié)的日志 -- 排查錯(cuò)誤的時(shí)候使用 logging.info('info message') # 正常的日志信息 logging.warning('warning message') # 警告,出現(xiàn)錯(cuò)誤,但是程序可以正常運(yùn)行 logging.error('error message') # 錯(cuò)誤 logging.critical('critical message') # 嚴(yán)重錯(cuò)誤,程序只能重啟才能正常運(yùn)行 # 2018-05-24 22:36:02,509 07 logging模塊.py[line:27] DEBUG debug message # 2018-05-24 22:36:02,509 07 logging模塊.py[line:28] INFO info message # 2018-05-24 22:36:02,510 07 logging模塊.py[line:29] WARNING warning message # 2018-05-24 22:36:02,510 07 logging模塊.py[line:30] ERROR error message # 2018-05-24 22:36:02,510 07 logging模塊.py[line:31] CRITICAL critical messagedatefmt更改日期格式
# datefmt更改日期格式 logging.basicConfig(level=logging.DEBUG,format=('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s'),datefmt = '%a, %d %b %Y %H:%M:%S') logging.debug('debug message') # 非常細(xì)節(jié)的日志 -- 排查錯(cuò)誤的時(shí)候使用 logging.info('info message') # 正常的日志信息 logging.warning('warning message') # 警告,出現(xiàn)錯(cuò)誤,但是程序可以正常運(yùn)行 logging.error('error message') # 錯(cuò)誤 logging.critical('critical message') # 嚴(yán)重錯(cuò)誤,程序只能重啟才能正常運(yùn)行 # Sun, 20 May 2018 16:18:20 07 logging模塊.py[line:11] DEBUG debug message # Sun, 20 May 2018 16:18:20 07 logging模塊.py[line:13] INFO info message # Sun, 20 May 2018 16:18:20 07 logging模塊.py[line:15] WARNING warning message # Sun, 20 May 2018 16:18:20 07 logging模塊.py[line:17] ERROR error message # Sun, 20 May 2018 16:18:20 07 logging模塊.py[line:19] CRITICAL critical messagefilename添加日志文件,filemode添加寫入文件格式a-追加,w-寫入
# filename添加日志文件,filemode文件打開(kāi)方式a追加,w寫入 logging.basicConfig(level=logging.DEBUG,format=('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s'),datefmt = '%a, %d %b %Y %H:%M:%S',filename='test.log',filemode='w') logging.debug('debug message') # 非常細(xì)節(jié)的日志 -- 排查錯(cuò)誤的時(shí)候使用 logging.info('info message') # 正常的日志信息 logging.warning('warning message') # 警告,出現(xiàn)錯(cuò)誤,但是程序可以正常運(yùn)行 logging.error('error message') # 錯(cuò)誤 logging.critical('critical message') # 嚴(yán)重錯(cuò)誤,程序只能重啟才能正常運(yùn)行 # test.log文件內(nèi)容 # Sun, 20 May 2018 16:18:20 07 logging模塊.py[line:11] DEBUG debug message # Sun, 20 May 2018 16:18:20 07 logging模塊.py[line:13] INFO info message # Sun, 20 May 2018 16:18:20 07 logging模塊.py[line:15] WARNING warning message # Sun, 20 May 2018 16:18:20 07 logging模塊.py[line:17] ERROR error message # Sun, 20 May 2018 16:18:20 07 logging模塊.py[line:19] CRITICAL critical message7.3 logger對(duì)象的配置
import logging # logger對(duì)象的方式配置 logger = logging.getLogger() # 吸星大法# 先創(chuàng)造一個(gè)格式 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') formatter1 = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') # 往文件中輸入 handler處理文件 fh = logging.FileHandler(filename='log.log') # 創(chuàng)造了一個(gè)能操作文件的對(duì)象fh fh.setFormatter(formatter) # 高可定制化 logger.addHandler(fh)# 往屏幕輸出 sh = logging.StreamHandler() sh.setFormatter(formatter1) # 高可定制化 logger.addHandler(sh)fh.setLevel(logging.ERROR) # 定義輸出的最低日志級(jí)別 sh.setLevel(logging.DEBUG)logging.debug('debug message') # 非常細(xì)節(jié)的日志 -- 排查錯(cuò)誤的時(shí)候使用 logging.info('info message') # 正常的日志信息 logging.warning('warning message') # 警告,出現(xiàn)錯(cuò)誤,但是程序可以正常運(yùn)行 logging.error('error message') # 錯(cuò)誤 logging.critical('critical message') # 嚴(yán)重錯(cuò)誤,程序只能重啟才能正常運(yùn)行# fh # 2018-05-24 22:51:42,426 - root - ERROR - error message # 2018-05-24 22:51:42,426 - root - CRITICAL - critical message # sh # 2018-05-24 22:50:39,370 - WARNING - warning message # 2018-05-24 22:50:39,370 - ERROR - error message # 2018-05-24 22:50:39,370 - CRITICAL - critical message# 說(shuō)明:logging庫(kù)提供了多個(gè)組件:Logger、Handler、Filter、Formatter。Logger對(duì)象提供應(yīng)用程序可直接使用的接口,Handler發(fā)送日志到適當(dāng)?shù)哪康牡?#xff0c;Filter提供了過(guò)濾日志信息的方法,Formatter指定日志顯示格式。另外,可以通過(guò):logger.setLevel(logging.Debug)設(shè)置級(jí)別,當(dāng)然,也可以通過(guò) # fh.setLevel(logging.Debug)單對(duì)文件流設(shè)置某個(gè)級(jí)別。轉(zhuǎn)載于:https://www.cnblogs.com/gongniue/p/9077570.html
總結(jié)
以上是生活随笔為你收集整理的第九章 常用模块(续)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 琴弦文字 - wpf行为
- 下一篇: react native基本调试技巧