計算機程序的開發過程當中,隨着程序代碼越寫越多,在一個文件裏代碼就會愈來愈長,愈來愈不容易維護。爲了編寫可維護的代碼,咱們把不少函數分組,分別放到不一樣的文件裏,這樣,每一個文件包含的代碼就相對較少,不少編程語言都採用這種組織代碼的方式。在 Python 中,一個.py 文件就稱之爲一個模塊(Module)。html
模塊分類:python
內置模塊 python安裝時自帶的程序員
擴展模塊 別人寫好的,安裝以後能夠直接使用算法
itchat模塊(和微信相關), beautifulsoap(爬蟲模塊), selenium(網頁自動化測試工具)shell
django tornado(框架)django
自定義模塊 本身寫的模塊 編程
提升了代碼的可維護性。json
當一個模塊編寫完畢,就能夠被其餘地方引用。安全
使用模塊能夠避免函數名和變量名衝突。bash
time模塊
python中,一般由如下三種方式來表示時間:
import time # 時間戳: print(time.time()) # 1520503969.847386 # 字符串格式化時間(兩種結果同樣): print(time.strftime('%x,%X')) # 04/24/18,16:09:53 print(time.strftime('%c')) # Tue Apr 24 16:11:12 2018 print(time.strftime('%Y-%M-%d,%H:%M:%S')) # 2018-14-24,16:14:08 print(time.strftime('%Y-%m-%d %X')) # 2018-03-08 18:12:49 print(time.strftime('%Y-%m-%d %H:%M:%S')) # 結構化時間: print(time.localtime()) # 本地時區的struct_time print(time.gmtime()) # UTC時區的struct_time
其中計算機認識的時間只能是'時間戳'格式,而程序員可處理的或者說人類能看懂的時間有: '格式化的時間字符串','結構化的時間'
幾種時間格式之間的轉換:
具體用法:
import time # 時間戳轉化爲結構化時間 # time.gmtime(時間戳) # UTC時間 # time.localtime(時間戳) # 當地時間 ret = time.localtime(2000000000) print(ret) # time.struct_time(tm_year=2033, tm_mon=5, tm_mday=18, tm_hour=11, tm_min=33, tm_sec=20, tm_wday=2, tm_yday=138, tm_isdst=0) # 結構化時間轉化爲格式化時間 print(time.strftime('%Y-%m-%d %H:%M:%S', ret)) # 2033-05-18 11:33:20 # 把一個結構化時間轉化爲格式化時間 print(time.strftime("%Y-%m-%d %X", time.localtime())) # 把一個格式化時間字符串轉化爲struct_time print(time.strptime('2018-04-24 17:37:06', '%Y-%m-%d %X'))
# 結構化時間 --> %a %b %d %H:%M:%S %Y串
# ctime,把一個時間戳轉化爲time.asctime()的形式 # 若是參數未給或者爲None的時候,將會默認time.time()爲參數 a = time.ctime(2000000000) print(a) # Wed May 18 11:33:20 2033 print(time.ctime(time.time())) # Tue Apr 24 17:41:56 2018 # asctime,把一個表示時間的元組或者struct_time表示爲這種形式:'Sun Jun 20 23:21:05 1993'。 # 若是沒有參數,則默認將time.localtime()做爲參數傳入。 print(time.asctime()) # Tue Apr 24 17:41:56 2018
python中時間日期格式化符號:
1 %y 兩位數的年份表示(00-99) 2 %Y 四位數的年份表示(000-9999) 3 %m 月份(01-12) 4 %d 月內中的一天(0-31) 5 %H 24小時制小時數(0-23) 6 %I 12小時制小時數(01-12) 7 %M 分鐘數(00=59) 8 %S 秒(00-59) 9 %a 本地簡化星期名稱 10 %A 本地完整星期名稱 11 %b 本地簡化的月份名稱 12 %B 本地完整的月份名稱 13 %c 本地相應的日期表示和時間表示 14 %j 年內的一天(001-366) 15 %p 本地A.M.或P.M.的等價符 16 %U 一年中的星期數(00-53)星期天爲星期的開始 17 %w 星期(0-6),星期天爲星期的開始 18 %W 一年中的星期數(00-53)星期一爲星期的開始 19 %x 本地相應的日期表示 20 %X 本地相應的時間表示 21 %Z 當前時區的名稱
datetime模塊:
import datetime print(datetime.datetime.now()) # 2018-03-08 21:04:15.544213
# y-m-d h:M:S 2018-04-24 17:00:00
# 計算從當前時間開始 比起y-m-d h:M:S過去了多少年 多少月 多少天 多少h,多少m,多少s
import time def pass_time(times): pass_time = time.strptime(times, '%Y-%m-%d %X') # 結構化時間 pass_time_stamp = time.mktime(pass_time) # 時間戳 time_stamp = time.time()-pass_time_stamp # 已通過去的時間戳 pass_times = time.localtime(time_stamp) # 結構化時間 now = zip(tuple(pass_times),tuple(time.localtime(0))) now1 = [(i[0]-i[1]) for i in now] # 數字型列表,對應年,月--- return '從當前時間開始,距離%s過去了%s年%s月%s日%s時%s分%s秒' %(times,now1[0],now1[1],now1[2],now1[3],now1[4],now1[5]) print(pass_time('2018-04-24 17:00:00'))
1 import random 2 # ---------------------------- 3 # 1.隨機小數,發紅包可用 4 print(random.random()) #0到1之間的隨機小數 5 print(random.uniform(1,3)) #大於1且小於3的隨機小數 6 7 # ---------------------------- 8 # 2.隨機整數,驗證碼可用 9 print(random.randint(1,5)) #大於1且小於等於5之間的整數 10 print(random.randrange(1,10,2)) #大於等於1且小於3之間的整數(且是全部的奇數) 11 12 # ---------------------------- 13 # 3.隨機選擇一個返回,抽獎 14 print(random.choice([1,'23',[4,5]])) 15 # ---------------------------- 16 # 4.隨機選擇返回多個,一次抽取多個 17 print(random.sample([1,'23',[4,5]],2)) #列表元素任意兩個組合輸出,後綴爲輸出個數 18 # ---------------------------- 19 20 21 # ---------------------------- 22 # 5.打亂列表順序,洗牌 23 item=[1,5,2,3,4] 24 random.shuffle(item) #打亂次序 25 print(item)
利用隨機數隨機生成6位驗證碼:
import random def ver_code(num): strs = '' lis1 = [chr(i) for i in range(65, 91)] lis2 = [str(i) for i in range(10)] ver1 = random.sample(lis1+lis2,num) for i in ver1: strs += i return strs print(ver_code(6))
def id_code(num): # num 字母在每一位被取到的機率相同 ret = '' for i in range(num): number = str(random.randint(0,9)) alph_num = random.randint(97,122) # A65 a97 +25 alph_num2 = random.randint(65,90) # A65 a97 +25 alph = chr(alph_num) alph2 = chr(alph_num2) choice = random.choice([alph,alph2]) choice = random.choice([number,choice]) ret += choice return ret print(id_code(6))
利用隨機數實現一個發紅包的編程
import random inp_money = float(input('紅包金額:')) inp_count = int(input('紅包個數:')) def red_packet(money, count): li = [] money = int(money*100) money_site = random.sample(range(1, money), count-1) money_site.extend([0, money]) money_site = sorted(money_site) for i in range(count): li.append(round((money_site[i+1]-money_site[i])*0.01, 2)) return li # 上面的定義li列表、for循環以及return 能夠簡寫成下面一行。 # return [round((sorted(money_site)[i + 1] - sorted(money_site)[i]) * 0.01, 2) for i in range(count)] ret = red_packet(inp_money, inp_count) print(ret)
利用隨機數隨機生成4位驗證碼,並帶模糊效果
from PIL import Image, ImageDraw, ImageFont, ImageFilter import random # 隨機字母: def rndChar(): return chr(random.randint(48, 57)) # 隨機顏色1: def rndColor(): return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255)) # 隨機顏色2: def rndColor2(): return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127)) # 240 x 60: width = 60 * 4 height = 60 image = Image.new('RGB', (width, height), (255, 255, 255)) # 建立Font對象: font = ImageFont.truetype('ariblk.ttf', 40) # 建立Draw對象: draw = ImageDraw.Draw(image) # 填充每一個像素: for x in range(width): for y in range(height): draw.point((x, y), fill=rndColor()) # 輸出文字: for t in range(4): draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2()) # 模糊: image = image.filter(ImageFilter.BLUR) image.save('code.jpg', 'jpeg')
# 有的文件可能轉義可能會出現問題,通常要在雙引號前加r,取消轉義,或者用雙斜槓表示
# 和當前執行的python文件工做目錄相關的工做路徑
os.getcwd() 獲取當前工做目錄,即當前python腳本工做的目錄路徑 os.chdir("dirname") 改變當前腳本工做目錄;至關於shell下cd os.curdir 返回當前目錄: ('.') os.pardir 獲取當前目錄的父目錄字符串名:('..')
# 和文件夾相關 os.makedirs('dirname1/dirname2') 可生成多層遞歸目錄,即文件夾下建立子文件夾,不會覆蓋原文件夾 os.removedirs('dirname1') 若目錄爲空,則刪除,並遞歸到上一級目錄,如若也爲空,則刪除,依此類推 os.mkdir('dirname') 生成單級目錄,即文件夾;至關於shell中mkdir dirname os.rmdir('dirname') 刪除單級空目錄,若目錄不爲空則沒法刪除,報錯;至關於shell中rmdir dirname os.listdir('dirname') 列出指定目錄下的全部文件和文件夾,包括隱藏文件,並以列表方式打印
# 和文件相關 os.remove() 刪除一個文件 os.rename("oldname","newname") 重命名文件/目錄 os.stat('path/filename') 獲取文件/目錄信息
# 和操做系統差別相關 os.sep 輸出操做系統特定的路徑分隔符,win下爲"\\",Linux下爲"/" os.linesep 輸出當前平臺使用的行終止符,win下爲"\t\n",Linux下爲"\n" os.pathsep 輸出用於分割文件路徑的字符串 win下爲;,Linux下爲: os.name 輸出字符串指示當前使用平臺。win->'nt'; Linux->'posix'
# 和執行系統命令相關 os.system("bash command") 運行shell命令,直接顯示,可是顯示的看不懂
os.popen("bash command).read() 運行shell命令,獲取執行結果,可看懂,如
os.popen('dir').read()
os.environ 獲取系統環境變量
# 路徑相關係列 os.path.abspath(path) 返回path規範化的絕對路徑,即從哪一個盤開始所有顯示出來 os.path.split(path) 將path分割成目錄和文件名二元組返回 os.path.dirname(path) 返回path的目錄。其實就是os.path.split(path)的第一個元素 os.path.basename(path) 返回path最後的文件名。如何path以/或\結尾,那麼就會返回空值。
即os.path.split(path)的第二個元素 os.path.exists(path) 若是path存在,返回True;若是path不存在,返回False os.path.isabs(path) 若是path是絕對路徑,返回True os.path.isfile(path) 若是path是一個存在的文件,返回True。不然返回False os.path.isdir(path) 若是path是一個存在的目錄,則返回True。不然返回False os.path.join(path1[, path2[, ...]]) 將多個路徑組合後返回,第一個絕對路徑以前的參數將被忽略 os.path.getatime(path) 返回path所指向的文件或者目錄的最後存取時間 os.path.getmtime(path) 返回path所指向的文件或者目錄的最後修改時間 os.path.getsize(path) 返回path的大小,文件夾的大小不許確,只顯示最大值4096字節,文件準確
ret = os.path.join('F:\天天視頻以及筆記','day5視頻') print(ret) ---F:\天天視頻以及筆記\day5視頻 # 組合成一個完整路徑
考慮如何計算文件夾中全部文件大小?示例路徑:F:\天天視頻以及筆記\python11期day01
import os def ram(file_name): sum = 0 for file in os.listdir(file_name): path = os.path.join(file_name, file) # 組合成一個完整路徑 if os.path.isfile(path): # 路徑下是文件 sum += os.path.getsize(path) else: sum += ram(path) return sum print(ram('F:\天天視頻以及筆記\python11期day01'))
import os def get_size(path): l = [path] sum_size = 0 while l: path = l.pop() # l = ['D:\python11\day2','D:\python11\day3'...] for item in os.listdir(path): #path = 'D:\python11' path2 = os.path.join(path, item) # path2 = 'D:\python11\day2' if os.path.isfile(path2): sum_size += os.path.getsize(path2) # sum = 文件的大小 + 0 else: l.append(path2) return sum_size print(get_size('D:\python11'))
# 複製文件的函數在os模塊中並不存在,由於複製文件並不是由操做系統提供的系統調用。可是咱們能夠調用shuti模塊中的copyfile()實現,該模塊至關於os模塊的一個補充。
# 說明,第一種方式採用了遞歸,雖然結果上也實現了,可是它相對來講比較耗內存。而第二種方式利用堆和棧的方式來講更加的友好
1 sys.argv 命令行參數是一個List,第一個元素是程序自己路徑 2 sys.exit(n) 退出程序,正常退出時exit(0) 3 sys.version 獲取Python解釋程序的版本信息 4 sys.maxint 最大的Int值 5 sys.path 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值 6 sys.platform 返回操做系統平臺名稱
序列化:
把對象(變量)從內存中變成可存儲或傳輸的過程稱之爲序列化,在Python中叫pickling,在其餘語言中也被稱之爲serialization,marshalling,flattening等等,都是一個意思。
序列化目的
序列化有三個模塊json和pickle,shelve
json 全部編程語言都通用的序列化格式,可是它支持的數據類型很是有限(只支持數字,字符串,序列,字典等,不支持元祖)
pickle 只能在python語言的程序之間傳遞數據使用,它支持python中全部數據類型
shelve 在py3以後纔有,python專有的序列化模塊,只針對文件。它只提供一個open方法,而且只能用字典形式訪問內容
json
Json模塊提供了四個功能:dumps、loads,這兩個只在內存中操做數據,主要在網絡傳輸中使用,和多個數據類型與文件打交道
dump、load ,這兩個是直接將對象序列化以後寫入文件,它依賴於一個文件句柄
import json dic={'k1':'v1','k2':'v2','k3':'v3'} str_dic = json.dumps(dic) #將字典轉換成字符串,轉換後的字典中的元素是由雙引號表示的 print(str_dic,type(str_dic))#{"k1": "v1", "k2": "v2", "k3": "v3"} <class 'str'> dic2 = json.loads(str_dic)#將一個字符串轉換成字典類型 print(dic2,type(dic2))#{'k1': 'v1', 'k2': 'v2', 'k3': 'v3'} <class 'dict'>
import json dic={'k1':'v1','k2':'v2','k3':'v3'} f = open('a.txt','w',encoding='utf-8') json.dump(dic,f,ensure_ascii=False) # 先接收要序列化的對象 再接受文件句柄 f.close() f = open('a.txt','r',encoding='utf-8') ret = json.load(f) print(type(ret),ret)
# json在寫入屢次dump的時候,不能對應執行屢次load來去除數據,pickle能夠
# json若是要寫入多個元素,應先將元素dumps序列化,再f.write(序列化+‘\n’)寫入文件。讀的時候先按行讀取,再使用loads將讀出來的字符串轉換成相應數據類型。
pickle(能夠把python中的任意數據類型序列化)
在硬盤上存儲文件有不少種方法,文本文件只是其中一種,若是想存儲列表或者對象之類的內容,能夠把對象轉換成字符串的形式寫入文本文件,可是若是要從文件中回覆對象,則這個就複雜化了。而python提供的pickle剛好能作到這一點:
# 經過pickle存儲python原生對象: import pickle D = {'a': 1, 'b': 2} F = open('datafile.pkl', 'wb') pickle.dump(D, F) # pickle.dump()能夠把任意對象序列化成一個bytes,而後就能夠把bytes寫入文件 F.close() # 取回字典,再用pickle模塊中load函數進行一次重建 F = open('datafile.pkl', 'rb') E = pickle.load(F) F.close() import pickle file = 'wish.data' lis = ['apple', 'banban'] f = open(file, 'wb') pickle.dump(lis, f) f.close() del lis f = open(file, 'rb') storedlis = pickle.load(f) print(storedlis) # 又獲得了列表
關於序列化自定義類的對象:
class A: def __init__(self,name,age): self.name=name self.age=age a = A('luffy',18) # import json # json.dumps(a) # 報錯,說明json沒法存儲實例化對象 import pickle ret = pickle.dumps(a) print(ret) # 打印出來的是一串字節 obj = pickle.loads(ret) print(obj) # 打印出對象地址 print(obj.__dict__) # {'name': 'luffy', 'age': 18}
在load的時候,必須擁有被load數據類型對應的類在內存裏面
shelve(用法專講連接https://www.tielemao.com/764.html)
python專有的序列化模塊,只針對文件,只提供了一個open方法,且是用key來訪問的,使用起來和字典相似。
import shelve f = shelve.open('a.txt') f['key'] = {'int': 10, 'float': 9.5, 'string': 'Sample data'} f['ds'] = '範圍分爲we分我發' f.close() # 直接對文件句柄進行操做,就能夠存儲文件,並且程序會給咱們自動建立三個後綴爲dir,bak,dat的文件,其中以bat結尾的文件存儲的就是b字節數據類型的數據 f1 = shelve.open('a.txt') a = f1['ds'] # 用key直接取出存儲的內容,若是key不存在則會報錯 f1.close() print(a) # 設置只讀模式 f2 = shelve.open('a.txt', flag='r') f2['key']['float'] = 3.14 # 修改結構中得值,不能夠 f2['space'] = 'dwd' # 覆蓋原來的結構,能夠 f1.close() f3 = shelve.open('a.txt') b = f3['key']['float'] # 對結構的值做修改,可是失敗了 f3.close() print(b) # 9.5
摘要算法,也稱哈希算法,它能將字符串轉成數字,不一樣的字符串轉成的數字必定不一樣,一般用16進製表示。不管在哪臺機器上,在何時計算,對相同的字符串結果老是同樣的
任何摘要算法都是把無限多的數據集合映射到一個有限的集合中。所以兩個不一樣的數據經過某個摘要算法也可能獲得相同的摘要,這種狀況被稱爲碰撞
用處:
密文驗證的時候加密
文件的一致性校驗
# md5算法:業界通用算法
# sha算法:安全係數更高,它有不少種(sha1,sha2,sha3等),後面數字越大,安全係數越高,且獲得的數字結果越長,計算時間越長。它的用法和md5相同,只需把md5換成sha1便可。
密文驗證的時候加密:
# hashhlib基本用法 import hashlib m = hashlib.md5() # 建立了一個md5算法對象 m.update('aptx4869'.encode('utf-8')) # 必須將字符串轉換成utf-8格式 print(m.hexdigest()) # 固定格式 # 6d1ce7aa0a1d988dc96a2abcd187b45a import hashlib m = hashlib.md5() m.update('apt'.encode('utf-8')) # 對源碼進行拆分加密,獲得的結果與總體加密一致 m.update('x4869'.encode('utf-8')) print(m.hexdigest()) # 6d1ce7aa0a1d988dc96a2abcd187b45a # 一段字符串直接進行摘要和分紅幾段摘要的結果是相同的
# 若是數字過於簡單,就能夠根據密文進行暴力破解得到源碼,安全性不是太好,所以能夠採用加鹽的方式加密 # 加鹽:在源碼的基礎上提早加一層靜態碼‘aptx4869’進行二次加密 m3 = hashlib.md5('aptx4869'.encode('utf-8')) m3.update('123456'.encode('utf-8')) print(m3.hexdigest()) # 21a36cc3275d352d92ee741b5425c330 # 這種方式較第一種比較安全性有所提升 # 動態加鹽: 對於用戶登陸,能夠經過相應的用戶登陸名進行一次加密,用密碼二次加密,密碼隨着用戶帳戶的變化而變化 username = 'Learning' password = 'aptx4869' m4 = hashlib.md5(username.encode('utf-8')) m4.update(password .encode('utf-8')) print(m4.hexdigest()) # b9112f155c08b48bba0e595236facc40 # 這種方式安全性大大的有所提升,登錄過程建議使用
文件的一致性校驗:(用來驗證文件內容是否被篡改)
# 該函數一次性所有交驗,若是文件較大,則耗時較大 import hashlib def check(filename): md5obj = hashlib.md5() with open(filename,'rb') as f: content = f.read() md5obj.update(content) return md5obj.hexdigest() # 該函數對於較大的文件,一次性以必定的字節數讀取驗證來驗證一致性 def check(filename): md5obj = hashlib.md5() with open(filename,'rb') as f: while True: content = f.read(1024) if content: md5obj.update(content) else: # 若是文件爲空 break return md5obj.hexdigest() ret1 = check('file1.txt') ret2 = check('file2.txt') print(ret1) print(ret2)
那麼問題來了,如何驗證兩個文件的一致性呢?
import hashlib def compare(filename1,filename2): md5sum = [] for file in [filename1,filename2]: md5 = hashlib.md5() with open(file,'rb') as f: while True: content = f.read(1024) if content: md5.update(content) else:break md5sum.append(md5.hexdigest()) if md5sum[0] == md5sum[1]:return True else :return False print(compare('f1','f2'))
import hashlib def loc(filname1, filname2): def check(filename): md5obj = hashlib.md5() with open(filename,'rb') as f: while True: content = f.read(5) if content: md5obj.update(content) else: # 非空 break return md5obj.hexdigest() if check(filname1) == check(filname2): return True else: return False print(loc('a.txt', 'a1.txt'))
在配置文件裏必須有分組(節),分組的組名能夠隨便起 ,能夠包含一個或多個組,能夠叫DEFAULT,它都具備特殊的意義(默認的是全局變量)
# 建立ini文件 import configparser config = configparser.ConfigParser() config["DEFAULT"] = {'luffy':'香蕉人', 'zero':'三把刀', 'sanzhi':'秋刀魚'} config['name'] = {'rojie':'onepiece', 'BB':'c', 'dd':'N'} # config['www.onepiece.online'] = {'我就試試集合行不行'} # 報錯,只能是字典形式 config['www.onepiece.online'] = {'我就試試集合行不行':'不行啊'} with open('one.ini', 'w') as f: config.write(f)
寫入後內容形式(這裏我是直接用電腦自帶的文本閱讀器打開的,默認是gbk格式,用其餘閱讀器非gbk會產生亂碼):
[DEFAULT]
zero = 三把刀
sanzhi = 秋刀魚
luffy = 香蕉人
[name]
dd = N
bb = c
rojie = onepiece
[www.onepiece.online]
我就試試集合行不行 = 不行啊
增刪改操做
# 增刪改操做 import configparser config=configparser.ConfigParser() config.read('one.ini') # 刪除節'name' config.remove_section('name') # 刪除節下的某個value值 config.remove_option('www.onepiece.online','我就試試集合行不行') # 判斷是否存在某個標題 print(config.has_section('name')) # 判斷標題section1下是否有user print(config.has_option('www.onepiece.online','我就試試集合行不行')) # 添加一個標題 config.add_section('EGG') #在標題EGG下添加name=egon,age=18的配置 config.set('EGG','name','egon') config.set('EGG','age','18')
總結:
# section 能夠直接操做他的對象來獲取全部的節信息
# option 能夠經過找到的節來查看全部的項
不會幫你自動添加日誌的內容,只能根據程序員寫的代碼完成功能
能夠經過一個參數去控制全局的日誌輸出狀況
能夠幫助開發者同時向文件和屏幕輸出內容
logging模塊提供5中日誌級別,從低到高一次:debug info warning error critical
默認是從warning模式開始顯示
日誌級別 CRITICAL = 50 #FATAL = CRITICAL ERROR = 40 WARNING = 30 #WARN = WARNING INFO = 20 DEBUG = 10
默認級別爲warning,它會默認打印在終端上
簡單用法:basicconfig
# 默認狀況下 只顯示警告(warning)及警告級別以上信息 import logging 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 = 'userinfo.log') logging.debug('debug message') # debug 調試模式 級別最低 logging.info('info message') # info 顯示正常信息 logging.warning('warning message') # warning 顯示警告信息 logging.error('error message') # error 顯示錯誤信息 logging.critical('critical message') # critical 顯示嚴重錯誤信息 ---WARNING:root:warning message ---ERROR:root:error message ---CRITICAL:root:critical message ---WARNING:root:warning message
logging.basicconfig()函數可配參數:
filename:用指定的文件名建立FiledHandler,這樣日誌會被存儲在指定的文件中。 filemode:文件打開方式,在指定了filename時使用這個參數,默認值爲「a」還可指定爲「w」。 format:指定handler使用的日誌顯示格式。 datefmt:指定日期時間格式。 level:設置rootlogger(後邊會講解具體概念)的日誌級別 stream:用指定的stream建立StreamHandler。能夠指定輸出到sys.stderr,sys.stdout或者文件,默認爲sys.stderr。若同時列出了filename和stream兩個參數,則stream參數會被忽略。 #格式 %(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:用戶輸出的消息
logging模塊組件:
# Logger 產生日誌對象 # Handler 接收日誌而後控制打印到不一樣地方: # FileHandler用來打印到文件中, # StreamHandler用來打印到終端 # Filter 過濾日誌對象 # Formatter 指定日誌顯示格式
logger對象配置:
import logging logger = logging.getLogger() # Logger用於產生日誌,實例化一個logger對象 # Handler對象:接收logger傳來的日誌,並控制輸出 fh = logging.FileHandler('test.log',encoding='utf-8') # 實例化一個文件句柄,並打印到文件 ch = logging.StreamHandler() # 打印到終端,沒有這步則只在文件中打印,在終端不顯示,終端就是電腦輸出界面 fmt = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s') # 定製化顯示格式 fh.setFormatter(fmt) ch.setFormatter(fmt) # 爲Handler對象綁定格式 logger.addHandler(fh) logger.addHandler(ch) # 和logger關聯的只有文件句柄 logger.setLevel(logging.WARNING) # 對象警告級別,從該級別以上開始警報 # 這裏我是直接給對象設置的該級別,意味着文件和終端都是同一級別,這裏能夠 # 對文件和終端分別設置不一樣的級別 logger.debug('debug message') # debug 調試模式 級別最低 logger.info('info message') # info 顯示正常信息 logger.warning('warning message') # warning 顯示警告信息 logger.error('error message') # error 顯示錯誤信息 logger.critical('critical message')
內置數據類型基礎上,collections模塊還提供了幾個額外數據類型:
counter:計數器
deque:雙端排列,能夠快速從另一側追加對象
namedtuple:生成可使用名字來訪問元素內容的tuple
orderdict:有序字典
defaultdict:帶有默認值的字典
namedtuple:
from collections import namedtuple point = namedtuple('point', ['x','y','z']) p = point(1,4,9) print(p.x) # 1 print(p.z) # 9 # 用來計算長方體體積 square = namedtuple('length',('x','y','z')) v = square(5,2,8) volume = v.x *v.y * v.z print(volume) # 80
deque:
它是爲了實現插入和刪除操做的雙向列表,適用於隊列和棧
from collections import deque lis = deque(['a','c','b']) lis.append(3) lis.appendleft(5) print(lis) # deque([5, 'a', 'c', 'b', 3]) # 這裏直接用list()能夠轉換成列表形式
Counter:
它的做用是用來跟蹤值出現的次數,屬於一個無序的容器類型,以字典的鍵值對形式存儲
基本用法:
from collections import Counter c = Counter('abcdeabcdabcaba') print(dict(c)) # {'e': 1, 'b': 4, 'd': 2, 'a': 5, 'c': 3} print(c['a']) # 5 print(c['b']) #4
計數器的更新,包含增長(update)和減小(subtract)兩種
from collections import Counter # update c = Counter('smile') c.update('lie') print(c['e']) # 2 d = Counter('beautiful') f = Counter('bee') d.update(f) print(d['e']) # 3 # subtract c = Counter('smile') c.subtract('lie') print(c['e']) # 0 d = Counter('beautiful') f = Counter('bee') d.subtract(f) print(d['e']) # -1
鍵的修改和刪除(del)
from collections import Counter c = Counter("abcdcba") c['a'] = 0 print(dict(c)) # {'d': 1, 'a': 0, 'c': 2, 'b': 2} del c['b'] print(dict(c)) # {'a': 0, 'c': 2, 'd': 1}
算數和集合操做
+、-、&、|操做也能夠用於Counter。其中&和|操做分別返回兩個Counter對象各元素的最小值和最大值。須要注意的是,獲得的Counter對象將刪除小於1的元素。
c = Counter(a=8, b=1) d = Counter(a=5, b=2) print(dict(c+d)) # {'a': 13, 'b': 3} print(dict(c-d)) # {'a': 3} 注意,它只保留正數計數的元素 print(dict(c&d)) # {'a': 5, 'b': 1} 求交集,min(c[x], d[x]) print(dict(c|d)) # {'b': 2, 'a': 8} 求並集,max(c[x], d[x])
Counter類經常使用操做
sum(c.values()) # 全部計數的總數 c.clear() # 重置Counter對象,注意不是刪除,最終返回None list(c) # 將c中的鍵轉爲列表 set(c) # 將c中的鍵轉爲set dict(c) # 將c中的鍵值對轉爲字典 c.items() # 轉爲(elem, cnt)格式的列表 Counter(dict(list_of_pairs)) # 從(elem, cnt)格式的列表轉換爲Counter類對象 c.most_common()[:-n:-1] # 取出計數最少的n個元素 c += Counter() # 移除0和負值
# 統計一篇英文文章內每一個單詞出現頻率,並返回出現頻率最高的前10個單詞及其出現次數
# 對['a','2',2,4,5,'2','b',4,7,'a',5,'d','a','z']該列表的數據進行計數統計
# 方法連接:http://www.cnblogs.com/LearningOnline/articles/8975806.html
Orderedict
保持key的順序
from collections import OrderedDict d = dict([('a', 3), ('b', 5), ('c', 3)]) print(d) # {'b': 5, 'c': 3, 'a': 3} d = OrderedDict([('a', 3), ('b', 5), ('c', 3)]) print(d) # OrderedDict([('a', 3), ('b', 5), ('c', 3)]) # 給這個樣子感受做用不大啊,用dict轉型過來順序又變了
對一個字典進行有序排序:
from collections import OrderedDict ordered_dict = OrderedDict() dic = { 4:'xxx', 1:'xxx', 2:'xxx', } for key in sorted(dic): ordered_dict[key] = dic[key] print(ordered_dict)
defaultdict(默認字典,是給字典中的value值設置默認值)
它最大的好處在於永遠不會在你使用key獲取值的時候報錯
有以下值集合 [
11
,
22
,
33
,
44
,
55
,
66
,
77
,
88
,
99
,
90.
..],將全部大於
66
的值保存至字典的第一個key中,將小於
66
的值保存至第二個key的值中。
from collections import defaultdict values = [11, 22, 33,44,55,66,77,88,99,90] my_dict = defaultdict(list) for value in values: if value>66: my_dict['k1'].append(value) else: my_dict['k2'].append(value) print(dict(my_dict))