第九章 常用模块(续)
1.序列化模塊? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
1.1 什么叫序列化
例:有一個班級信息字典{'10010000':{'name':'zhangsan', 'age':22, 'class':'python21'},...},在程序結束后需要保存,而在python中只有字符串能保存到文件中。再次使用字典的時候,可以使用eval轉化,但是非常不安全,所以引入了序列化
序列化就是 數據類型轉化成字符串的過程 -- 數據類型 --> 字符串的過程
字符串化也叫做序列化
1.2 為什么要用序列化呢?(固態存儲、網絡傳輸)
數據從內存到文件
數據在網絡上傳輸,在網線上能夠傳遞的只有 010101 -- 字節 -- 字符串 -- 字典
1.3 python中的序列化模塊都有哪些?
json 通用的 支持的數據類型 list tuple dict
pickle 在python中通用的 支持幾乎所有python中的數據類型
shelve 在py3種不是很好用,在python中使用的便捷的序列化工具
2.json模塊? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
基于內存的操作
import json dic = {'k': 'v'} # 基于內存的操作(和內存交互的) print(type(dic)) # <class 'dict'> json_dic = json.dumps(dic) # 所有引號都會變成雙引號字典 轉化成字符串的過程 -- 序列化 print(json_dic) # {"k": "v"} print(dic) # {'k': 'v'} print(type(json_dic)) # <class 'str'> print(json.loads(json_dic)) # 字符串 轉回其他數據類型的過程 -- 反序列化 # {'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多條數據 # 每一條數據dumps一下 編輯成字符串,然后打開文件 write寫進文件里 \n # 讀取的時候按照標志讀取或者按行讀 # 讀出來之后 在使用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看不到轉碼后的內容 class A:def __init__(self, name):self.name = namealex = A('alex') # json.dumps(alex) # 支持的數據類型有限 # 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模塊相對json模塊的優勢一:支持幾乎所有python中的數據類型
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模塊相對json模塊的優勢二:多次load內容比較簡單
# 多次寫入文件 with open('bbb', 'wb') as f:pickle.dump(alex, f)pickle.dump(alex, f)pickle.dump(alex, f)pickle.dump(alex, f)# 多次讀取內容 with open('bbb', 'rb') as f:try:while True:obj = pickle.load(f)print(obj.name)except EOFError:pass # alex # alex # alex # alex總結:
1.pickle支持更多的數據類型
2.pickle的結果是二進制
3.pickle在和文件交互的時候可以被多次load
4.hashlib摘要算法模塊? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Python的hashlib提供了常見的摘要算法,如MD5,SHA1等等。
什么是摘要算法呢?摘要算法又稱哈希算法、散列算法。它通過一個函數,把任意長度的數據轉換為一個長度固定的數據串(通常用16進制的字符串表示)。
摘要算法就是通過摘要函數f()對任意長度的數據data計算出固定長度的摘要digest,目的是為了發現原始數據是否被人篡改過。
摘要算法之所以能指出數據是否被篡改過,就是因為摘要函數是一個單向函數,計算f(data)很容易,但通過digest反推data卻非常困難。而且,對原始數據做一個bit的修改,都會導致計算出的摘要完全不同。
最常使用的兩種算法sha/md5
4.1 使用hashlib模塊獲取字符串的MD5值
import hashlib# 例:使用hashlib模塊獲取字符串的md5值 md5obj = hashlib.md5() # 實例化一個MD5摘要算法的對象 md5obj.update('alex3714'.encode('utf-8')) # 使用md5算法的對象來操作字符串(bytes類型) ret = md5obj.hexdigest() ## 獲取算法的結果 hex + digest 16進制+消化 print(ret, type(ret), len(ret)) # aee949757a2e698417463d47acac93df <class 'str'> 32
4.2?使用hashlib模塊獲取字符串的sha值
# sha算法,后面的數字越大,結果越長 md5obj = hashlib.sha256() # 實例化一個sha摘要算法的對象 md5obj.update('alex3714'.encode('utf-8')) # 使用sha算法的對象來操作字符串(bytes類型) ret = md5obj.hexdigest() ## 獲取算法的結果 hex + digest 16進制+消化 print(ret, type(ret), len(ret)) #sha1 8a003668a9c990f15148f9e4046e1410781533b6 <class 'str'> 40 #sha256 1e1c67170a2136ba7e18ffee2461fdbcdcf0884d9d9d005d4ab8c8733a15f8ab <class 'str'> 644.3 高級用法 -- 加鹽
# 例:使用md5算法進行加密認證 md5obj = hashlib.md5('tesla'.encode('utf-8')) # 加鹽過程 md5obj.update('alex3714'.encode('utf-8')) # 使用md5算法的對象來操作字符串(bytes類型) ret = md5obj.hexdigest() ## 獲取算法的結果 hex + digest 16進制+消化 print(ret, type(ret), len(ret)) # aee949757a2e698417463d47acac93df <class 'str'> 32 # 加鹽前 # 7dafaec086d0ddae18b63e4fffafbf8e <class 'str'> 32 # 加鹽后動態加鹽
# 動態加鹽 -- 有些網站,一旦注冊了,用戶名就不能更改了,原因是用戶名當鹽 username = 'alex' md5obj = hashlib.md5(username.encode('utf-8')) # 加鹽過程 md5obj.update('alex3714'.encode('utf-8')) # 使用md5算法的對象來操作字符串(bits類型) ret = md5obj.hexdigest() ## 獲取算法的結果 hex + digest 16進制+消化 print(ret, type(ret), len(ret)) # ee838c58e5bb3c9e687065edd0ec454f <class 'str'> 324.4 校驗文件的一致性
# 校驗文件的一致性 # 自動化 -- python代碼來做驗證 md5obj = hashlib.md5() # 實例化一個MD5摘要算法的對象 md5obj.update('alex3714'.encode('utf-8')) #使用md5算法的對象來操作字符串(bytes類型) print(md5obj.hexdigest()) # aee949757a2e698417463d47acac93dfmd5obj = hashlib.md5() md5obj.update('alex'.encode('utf-8')) md5obj.update('3714'.encode('utf-8')) #使用md5算法的對象來操作字符串(bytes類型) print(md5obj.hexdigest()) # aee949757a2e698417463d47acac93df # 說明:分多次對同一個字符串進行摘要和一次性對這個字符串的摘要的結果是相同的
5.configparser模塊 -- ini配置文件? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
該模塊適用于配置文件的格式與windows ini文件類似,可以包含一個或多個節(section),每個節可以有多個參數(鍵=值)。
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# 實例化config對象 config = configparser.ConfigParser()# 給config添加內容 # []內為配置文件內的組名 # 后面的字典為組內配置的鍵值對 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的方法將相應配置,寫入文件config.write(configfile)5.3 查找文件
import configparserconfig = configparser.ConfigParser()#---------------------------查找文件內容,基于字典的形式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會默認default的鍵print(key)print(config.options('bitbucket.org')) # 同for循環,找到'bitbucket.org'下所有鍵print(config.items('bitbucket.org')) #找到'bitbucket.org'下所有鍵值對print(config.get('bitbucket.org','compression')) # yes get方法Section下的key對應的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 默認情況下Python的logging模塊將日志打印到了標準輸出中,且只顯示了大于等于WARNING級別的日志,這說明默認的日志級別設置為WARNING(日志級別等級CRITICAL > ERROR > WARNING > INFO > DEBUG),默認的日志格式為日志級別:Logger名稱:用戶輸出消息。
日志級別
logging.debug('debug message') # 非常細節的日志 -- 排查錯誤的時候使用 # DEBUG:root:debug message logging.info('info message') # 正常的日志信息 # INFO:root:info message logging.warning('warning message') # 警告,出現錯誤,但是程序可以正常運行 # WARNING:root:warning message logging.error('error message') # 錯誤 # ERROR:root:error message logging.critical('critical message') # 嚴重錯誤,程序只能重啟才能正常運行 # CRITICAL:root:critical message7.2 格式化輸出
靈活配置日志級別,日志格式,輸出位置
logging.basicConfig()函數中可通過具體參數來更改logging模塊默認行為,可用參數有:filename:用指定的文件名創建FiledHandler,這樣日志會被存儲在指定的文件中。 filemode:文件打開方式,在指定了filename時使用這個參數,默認值為“a”還可指定為“w”。 format:指定handler使用的日志顯示格式。 datefmt:指定日期時間格式。 level:設置rootlogger(后邊會講解具體概念)的日志級別 stream:用指定的stream創建StreamHandler。可以指定輸出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默認為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用戶輸出的消息format添加格式
# 靈活配置日志級別,日志格式,輸出位置: # format添加格式 logging.basicConfig(level=logging.DEBUG,format=('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')) # 默認包含warning及以上的信息 logging.debug('debug message') # 非常細節的日志 -- 排查錯誤的時候使用 logging.info('info message') # 正常的日志信息 logging.warning('warning message') # 警告,出現錯誤,但是程序可以正常運行 logging.error('error message') # 錯誤 logging.critical('critical message') # 嚴重錯誤,程序只能重啟才能正常運行 # 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') # 非常細節的日志 -- 排查錯誤的時候使用 logging.info('info message') # 正常的日志信息 logging.warning('warning message') # 警告,出現錯誤,但是程序可以正常運行 logging.error('error message') # 錯誤 logging.critical('critical message') # 嚴重錯誤,程序只能重啟才能正常運行 # 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文件打開方式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') # 非常細節的日志 -- 排查錯誤的時候使用 logging.info('info message') # 正常的日志信息 logging.warning('warning message') # 警告,出現錯誤,但是程序可以正常運行 logging.error('error message') # 錯誤 logging.critical('critical message') # 嚴重錯誤,程序只能重啟才能正常運行 # test.log文件內容 # 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對象的配置
import logging # logger對象的方式配置 logger = logging.getLogger() # 吸星大法# 先創造一個格式 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') # 創造了一個能操作文件的對象fh fh.setFormatter(formatter) # 高可定制化 logger.addHandler(fh)# 往屏幕輸出 sh = logging.StreamHandler() sh.setFormatter(formatter1) # 高可定制化 logger.addHandler(sh)fh.setLevel(logging.ERROR) # 定義輸出的最低日志級別 sh.setLevel(logging.DEBUG)logging.debug('debug message') # 非常細節的日志 -- 排查錯誤的時候使用 logging.info('info message') # 正常的日志信息 logging.warning('warning message') # 警告,出現錯誤,但是程序可以正常運行 logging.error('error message') # 錯誤 logging.critical('critical message') # 嚴重錯誤,程序只能重啟才能正常運行# 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# 說明:logging庫提供了多個組件:Logger、Handler、Filter、Formatter。Logger對象提供應用程序可直接使用的接口,Handler發送日志到適當的目的地,Filter提供了過濾日志信息的方法,Formatter指定日志顯示格式。另外,可以通過:logger.setLevel(logging.Debug)設置級別,當然,也可以通過 # fh.setLevel(logging.Debug)單對文件流設置某個級別。轉載于:https://www.cnblogs.com/gongniue/p/9077570.html
總結
以上是生活随笔為你收集整理的第九章 常用模块(续)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 琴弦文字 - wpf行为
- 下一篇: react native基本调试技巧