一、雙層裝飾器html
單層裝飾器python
雙層裝飾器json
原理windows
二、字符串的格式化api
三、format字符串格式化網絡
四、生成器app
五、遞歸ide
六、模塊的安裝函數
七、json模塊工具
八、pickle模塊
九、time模塊
十、datetime模塊
十一、logging模塊
仍是老樣,沒有改變:
USER_INFO = {} def check_login(func): def inner(*args, **kwargs): if USER_INFO.get("is_login", None): # 用get方法拿字典裏面的內容,若是字典裏面沒有咱們要拿的參數,不會報錯,給他默認返回的爲None ret = func(*args, **kwargs) return ret else: print("請登陸") return inner def check_admin(func): # 判斷是否爲管理員用戶 def inner(*args, **kwargs): if USER_INFO.get("is_login", None): if USER_INFO.get("user_type", None) == 2: # 若是用戶類型等於2,表示爲管理員用戶 ret = func(*args, **kwargs) return ret else: print("無權限查看") # 否者無權限查看 else: print("請登陸") return inner @check_admin def index(): # 超級管理員能夠查看 print("index") @check_login def home(): # 登陸能夠查看 """ 普通用戶的功能 :return: """ print("home") def login(): # 登陸 user = input("請輸入用戶名:") if user == "admin": USER_INFO["is_login"] = True USER_INFO["user_type"] = 2 else: # 否者若是不爲admin,表示登陸的用戶爲普通用戶 USER_INFO["is_login"] = True USER_INFO["is_login"] = 1 def main(): while True: inp = input("一、登陸;二、查看信息;3超級管理員\n>>>") if inp == "1": login() elif inp == "2": home() elif inp == "3": index() main()
輸出:
一、登陸;2、查看信息;3超級管理員 >>>2 請登陸 一、登陸;2、查看信息;3超級管理員 >>>3 請登陸 一、登陸;2、查看信息;3超級管理員 >>>1 請輸入用戶名:user 一、登陸;2、查看信息;3超級管理員 >>>2 home 一、登陸;2、查看信息;3超級管理員 >>>3 無權限查看 一、登陸;2、查看信息;3超級管理員 >>>1 請輸入用戶名:admin 一、登陸;2、查看信息;3超級管理員 >>>2 home 一、登陸;2、查看信息;3超級管理員 >>>3 index 一、登陸;2、查看信息;3超級管理員 >>>
新變化:
# 從版本以一中咱們能夠看到不少咱們的check_admin裏面重複了check_login的代碼(check_admin又判斷登陸,又判斷權限), # 若是咱們又加上了超級管理員,那咱們就會又寫一個重複的裝飾器, # 因此咱們須要用到雙層裝飾器,先用check_login,判斷是否登陸,而後用check_admin判斷是否爲管理員 USER_INFO = {} def check_login(func): def inner(*args, **kwargs): if USER_INFO.get("is_login", None): # 用get方法拿字典裏面的內容,若是字典裏面沒有咱們要拿的參數,不會報錯,給他默認返回的爲None ret = func(*args, **kwargs) return ret else: print("請登陸") return inner def check_admin(func): # 判斷是否爲管理員用戶 def inner(*args, **kwargs): if USER_INFO.get("user_type", None) == 2: # 若是用戶類型等於2,表示爲管理員用戶 ret = func(*args, **kwargs) return ret else: print("無權限查看") # 否者無權限查看 return inner # 爲何check_login寫上面,咱們從下向上看,從index()開始, # 能夠看到先用admin裝飾後,好比變成了nindex這個函數,而後再用login裝飾進行裝飾,好比又變成了nnindex,而後python是從上向下執行, # 因此python會執行nnindex,判斷是否登陸,而後在執行nindex,判斷是否爲管理員,若是沒有登陸, # 提示登陸,若是已經登陸(不爲管理員),提示無權限 @check_login @check_admin def index(): # 管理員能夠查看 """ 管理員的功能 :return: """ print("index") @check_login def home(): # 登陸能夠查看 """ 普通用戶的功能 :return: """ print("home") def login(): # 登陸 user = input("請輸入用戶名:") if user == "admin": USER_INFO["is_login"] = True USER_INFO["user_type"] = 2 else: # 否者若是不爲admin,表示登陸的用戶爲普通用戶 USER_INFO["is_login"] = True USER_INFO["is_login"] = 1 def main(): while True: inp = input("一、登陸;二、查看信息;3超級管理員\n>>>") if inp == "1": login() elif inp == "2": home() elif inp == "3": index() main()
輸出:
一、登陸;2、查看信息;3超級管理員 >>>2 請登陸 一、登陸;2、查看信息;3超級管理員 >>>3 請登陸 一、登陸;2、查看信息;3超級管理員 >>>1 請輸入用戶名:user 一、登陸;2、查看信息;3超級管理員 >>>2 home 一、登陸;2、查看信息;3超級管理員 >>>3 無權限查看 一、登陸;2、查看信息;3超級管理員 >>>1 請輸入用戶名:admin 一、登陸;2、查看信息;3超級管理員 >>>2 home 一、登陸;2、查看信息;3超級管理員 >>>3 index 一、登陸;2、查看信息;3超級管理員 >>>
輸出效果徹底同樣,注意看v2的註釋
裝飾器的原理(多層原理也同樣):
%[(name)] [flags] [width].[precision] typecode
# 字符串格式化 # %[(name)] [flags] [width].[precision] typecode # 常規的格式化 string = "博客網址:www.cnblogs.com/%s,園齡:%d個月" % ("smelond", 1) print(string) # %[(name)]可選,用於指定的key: string = "博客網址:www.cnblogs.com/%(name)s,園齡:%(age)d個月" % {"name": "smelond", "age": 1} # 用字典方式 print(string) # flags 可選,可供選擇的值有(據說沒卵用) # + 右對齊:正數前加正號,負數前加負號 # - 左對齊:正數前無符號,負數前加負號 # 空格 右對齊:正數前加空格,負數前加負號 # 0 右對齊:正數前無符號,負數前加負號;用0填充空白處 string = "博客網址:www.cnblogs.com/%(name)+20s,園齡:%(age)-10d個月" % {"name": "smelond", "age": 1} # 佔有20個空格,smelond在其中,向右對齊 print(string) # width 可選,佔有寬度 # .precision 可選,小數點後保留的位數 string = "數值:%(p).2f" % {"p": 1.23656} # 在後面加上.而後數字,表明保留幾位,有四捨五入功能 print(string) # typecode 必選 # s,獲取傳入對象的__str__方法的返回值,並將其格式化到指定位置 # r,獲取傳入對象的__repr__方法的返回值,並將其格式化到指定位置(面向對象內容) # c,整數:將數字轉換成其unicode對應的值,10進制範圍爲 0 <= i <= 1114111(py27則只支持0-255);字符:將字符添加到指定位置 # o,將整數轉換成 八 進製表示,並將其格式化到指定位置 # x,將整數轉換成十六進制表示,並將其格式化到指定位置 string = "%c___%o___%x" % (65, 15, 15) # 將十進制轉換爲其餘進制(A,17,f) print(string) # d,將整數、浮點數轉換成 十 進製表示,並將其格式化到指定位置 # e,將整數、浮點數轉換成科學計數法,並將其格式化到指定位置(小寫e) # E,將整數、浮點數轉換成科學計數法,並將其格式化到指定位置(大寫E) # f, 將整數、浮點數轉換成浮點數表示,並將其格式化到指定位置(默認保留小數點後6位) # F,同上 string = "%d--------%f--------%e--------%E-------%.2ef" % (100000000, 1.23456, 10000000, 10000000, 10000000) print(string) # g,自動調整將整數、浮點數轉換成 浮點型或科學計數法表示(超過6位數用科學計數法),並將其格式化到指定位置(若是是科學計數則是e;) # G,自動調整將整數、浮點數轉換成 浮點型或科學計數法表示(超過6位數用科學計數法),並將其格式化到指定位置(若是是科學計數則是E;) string = "%g-------%g-------%G-------%G" % (10000000, 100, 10000000, 100) print(string) # %,當字符串中存在格式化標誌時,須要用 %%表示一個百分號 string = "name:%s %% %%%%" % "smelond" # 若是須要輸出一個%,可是前面已經有了一個佔位符,那就須要輸出%%才能表明一個%,否者會報錯,須要輸出%%,就須要%%%% print(string) # # 注:Python中百分號格式化是不存在自動將整數轉換成二進制表示的方式
博客網址:www.cnblogs.com/smelond,園齡:1個月 博客網址:www.cnblogs.com/smelond,園齡:1個月 博客網址:www.cnblogs.com/ smelond,園齡:1 個月 數值:1.24 A___17___f 100000000--------1.234560--------1.000000e+07--------1.000000E+07-------1.00e+07f 1e+07-------100-------1E+07-------100 name:smelond % %%
# [[fill]align] [sign] [#] [0] [widht] [,] [.precision] [type]
# fill 【可選】空白處填充的字符 # align 【可選】對齊方式(需配合width使用) # < ,內容左對齊 # > ,內容右對齊(默認) # =,內容右對齊,將符號放置在填充字符的左側,且只對數字類型有效。 即便:符號 + 填充物 + 數字 # ^ ,內容居中 # sign 【可選】有無符號數字 # +,正號加正,負號加負; # -,正號不變,負號加負; # 空格 ,正號空格,負號加負; # # 【可選】對於二進制、八進制、十六進制,若是加上#,會顯示 0b/0o/0x,不然不顯示 # , 【可選】爲數字添加分隔符,如:1, 000, 000 # width 【可選】格式化位所佔寬度 # .precision 【可選】小數位保留精度 # type 【可選】格式化類型 # 傳入」 字符串類型 「的參數 # s,格式化字符串類型數據 # 空白,未指定類型,則默認是None,同s # 傳入「 整數類型 」的參數 # b,將10進制整數自動轉換成2進製表示而後格式化 # c,將10進制整數自動轉換爲其對應的unicode字符 # d,十進制整數 # o,將10進制整數自動轉換成8進製表示而後格式化; # x,將10進制整數自動轉換成16進製表示而後格式化(小寫x) # X,將10進制整數自動轉換成16進製表示而後格式化(大寫X) # 傳入「 浮點型或小數類型 」的參數 # e, 轉換爲科學計數法(小寫e)表示,而後格式化; # E, 轉換爲科學計數法(大寫E)表示,而後格式化; # f , 轉換爲浮點型(默認小數點後保留6位)表示,而後格式化; # F, 轉換爲浮點型(默認小數點後保留6位)表示,而後格式化; # g, 自動在e和f中切換 # G, 自動在E和F中切換 # % ,顯示百分比(默認顯示小數點後6位)
# 兩個最基本的格式化 string = "asdfasgsdf__{0}__asdf__{0}__adhkg__{1}__".format(123, "smelond") print(string) # asdfasgsdf__123__asdf__123__adhkg__smelond__ string = "___{name:s}___{age:d}___{name:s}".format(name="smelond", age=16) print(string) # ___smelond___16___smelond # 一些經常使用的用法 # 空白處填充*,^字符居中,20個空格,s:字符串形式{:*^20s} # +有符號數值,d:十進制{:+d} # x 直接轉換爲16進制 # #若是後面輸入的爲x,那就轉換爲16進制後再前面加上0x{:#x} string = "_____{:*^20s}_____{:+d}_____{:x}_____{:#x}".format("smelond", 123, 15, 15) print(string) # _____******smelond*******_____+123_____f_____0xf string = "百分比:{:%}".format(1.2345) print(string) # 百分比:123.450000%
# 一些經常使用的用法 tpl = "i am {},age {},{}".format("seven", 16, "smelond") print(tpl) # i am seven,age 16,smelond tpl = "i am {},age {},{}".format(*["seven", 16, "smelond"]) print(tpl) # i am seven,age 16,smelond,注意,若是是列表要在前面加上* tpl = "i am {0},age {1}, really {0}".format("seven", 16) print(tpl) # i am seven,age 16, really seven tpl = "i am {0},age {1}, really {0}".format(*["seven", 16]) print(tpl) # i am seven,age 16, really seven,列表須要加上* tpl = "i am {name}, age {age}, really {name}".format(name="smelond", age=16) print(tpl) # i am smelond, age 16, really smelond tpl = "i am {name}, age {age}, really {name}".format(**{"name": "smelond", "age": 16}) print(tpl) # i am smelond, age 16, really smelond,注意,若是是字典須要加上兩個* tpl = "i am {0[0]}, age {0[1]}, really {1[2]}".format([1, 2, 3], [11, 22, 33]) print(tpl) # i am 1, age 2, really 33,列表裏面的列表 tpl = "i am {:s}, age {:d}".format("smelond", 16) print(tpl) # i am smelond, age 16 tpl = "i am {name:s}, age {age:d}".format(name="smelond", age=16) print(tpl) # i am smelond, age 16 tpl = "i am {name:s}, age {age:d}".format(**{"name": "smelond", "age": 16}) print(tpl) # i am smelond, age 16,字典須要加上** tpl = "numbers:{:b},{:o},{:d},{:x},{:X},{:%}".format(15, 15, 15, 15, 15, 15.87612) print(tpl) # s:1111,17,15,f,F,1500.000000% tpl = "numbers:{0:b},{0:o},{0:d},{0:x},{0:X},{0:%}".format(15) print(tpl) # s:1111,17,15,f,F,1500.000000% tpl = "numbers:{num:b},{num:o},{num:d},{num:x},{num:X},{num:%}".format(num=15) print(tpl) # s:1111,17,15,f,F,1500.000000%
# 普通函數 # def func(): # return 123 # # # ret = func() # 執行函數拿結果 # 生成器 def func(): # print("start") print(111) yield 1 print(222) yield 2 print(333) yield 3 # 若是在函數裏面出現了yield,這個函數就稱之爲生成器 ret = func() print(ret) # for i in ret: # print(i) # 輸出 # 循環第一次的時候就進入func函數裏面去,進入後拿走yield後面的值,因此輸出1,而後循環第二次, # 第二次進入func函數時,找到上一次結尾的位置,從結尾的位置又開始循環(往下走),因此就是輸出2 # 而後第三次 r1 = ret.__next__() # 進入函數找到yield,獲取yield後面的數據,而後咱們就拿到了1 print(r1) r2 = ret.__next__() # 進入函數找到yield,獲取yield後面的數據,而後咱們就拿到了2 print(r2) r3 = ret.__next__() # 進入函數找到yield,獲取yield後面的數據,而後咱們就拿到了3 print(r3) # r4 = ret.__next__() # print(r4) # 從函數裏面能夠看到沒有第4個yield,因此這句要報錯 #輸出: 111 1 222 2 333 3
# 基於生成器實現range功能 def myrange(arg): # 至關於這是一個生成器 start = 0 while True: if start > arg: return yield start start += 1 ret = myrange(3) # for i in ret: # print(i) r = ret.__next__() print(r) r = ret.__next__() print(r) r = ret.__next__() print(r) r = ret.__next__() print(r) # r = ret.__next__() # print(r)#第四次確定報錯,由於只循環3次,從0開始 輸出: 0 1 2 3
本身拿着windows自帶的畫圖工具畫的,將就看吧,是有點醜
代碼貼上
# 一個遞給另一個,一個簡單的原理 def d(): r = "end" # 將字符串end賦給r return r # 返回一個變量r def c(): r = d() # 拿到函數d的返回值 return r def b(): r = c() # 拿到函數c的返回值 return r def a(): r = b() # 拿到函數b的返回值 print(r) # 拿到結果後輸出 a() # 輸出end # 遞歸 # 執行第一次時的效果 def func(n): # 如今n=1 n += 1 # n等於2 if n >= 4: # 當若是n>=4的時候 return "end" # 遇到return直接退出,而後返回一個字符串end return func(n) # 上面if若是沒執行,確定會執行這句,返回func函數,如今的n=2 r = func(1) # 傳入實參1到func函數裏去慢慢執行,而後接收返回值 print(r) #輸出end
用遞歸實現一個1*2*3*4*5*6*7:
def func(n, x): # n=1,x=1.......n=2,x=2.......n=3,x=6 n += 1 # n=2.......n=3.......n=4 x *= n # x=x*n,x=2.......x=x*n,x=6.......x=x*n,x=24 if n >= 7: # 直到n等於7的時候,將x返回 return x return func(n, x) # n=2,x=2.......n=3,x=6....... r = func(1, 1) print(r) 輸出:5040
def func(num): if num == 1: return 1 return num * func(num - 1) x = func(7) print(x) 輸出:5040
事實證實,我太笨了,我那個太複雜了,並且全是運算,可是老師的感受就輕快明瞭
# 導入模塊 # 單模塊 import call_m # 直接調用當前目錄下的call_m.py文件 import lib.commons # 調用lib目錄下的commons.py文件 # 嵌套在文件夾下的模塊 from lib import commons from src import commons as xxx # 若是重名,咱們能夠用as給他作一個別名 # call_m.login() # 輸出裏面的方法,就至關於調用了裏面的函數 # lib.commons.logout()
安裝requests模塊
pip3 install requests
json只能處理基本的數據類型
import json # json只能處理基本的數據類型 dic = {"k1": "v1"} print(dic, type(dic)) # 用json模塊將python的基本數據類型轉換成爲字符串形式 result = json.dumps(dic) print(result, type(result)) s1 = '{"k1":123}' # json將python字符串形式轉換成爲基本數據類型 dic = json.loads(s1) print(dic, type(dic)) # py基本數據類型轉換字符串 r = json.dumps([11, 22, 33]) # li = "['smelond','amanda']" #這種方法不行,由於其餘語言裏面 ' 和 "跟python不同 li = '["smelond","amanda"]' # 反序列化時,必定要使用 " print(r, type(r)) ret = json.loads(li) print(ret, type(ret)) li = [11, 22, 33] json.dump(li, open("db", "w")) # dump先把他進行序列化,而後寫到文件裏面 li = json.load(open("db", "r")) # 從文件裏面把字符串讀出來,讀出來後會轉換成爲列表類型 print(li, type(li))
用json加requests模塊調用天氣的api接口
import json import requests import sys response = requests.get("http://www.sojson.com/open/api/weather/json.shtml?city=雙流") response.encoding = "utf-8" dic = json.loads(response.text) print(dic)
json/pickle
json更加適合跨語言操做,由於它傳遞的是字符串,基本數據類型
pickle,對python的全部類型的序列化,僅適用與python
pickle支持任何的類型
# pickle支持任何的類型 import pickle # dumps a loads li = [11, 22, 33] r = pickle.dumps(li) # 字符方式 print(r) result = pickle.loads(r) print(result) # dump a load li = [11, 22, 33] pickle.dump(li, open("db", "wb")) ##pickle是以字符方式存取,因此要加上b resul = pickle.load(open("db", "rb")) # 讀取 print(resul)
import time print(time.process_time()) # 測量處理器運算時間,不包括sleep時間,不穩定 print(time.altzone) # 返回與utc時間的時間差,以秒計算 print(time.asctime()) # 返回時間格式「Sat Dec 30 17:32:59 2017」 print(time.localtime()) # 返回本地時間的struct time對象格式 tm = time.localtime() # 將返回的struct time格式的時間賦給tm print("{}-{}".format(tm.tm_year, tm.tm_mon)) # 用format輸出年月 print(time.gmtime(time.time() - 8000000)) # 返回utc時間的struc時間對象格式 print(time.asctime(time.localtime())) # 返回時間格式「Sat Dec 30 17:39:47 2017」 print(time.ctime()) # 返回時間格式「Sat Dec 30 17:41:44 2017」同上 # 日期字符串 轉換 時間戳 string_2_struct = time.strptime("2017/12/30", "%Y/%m/%d") # 將日期字符串 轉換 struct時間對象格式 print(string_2_struct) struct_2_stamp = time.mktime(string_2_struct) # 將struct時間對象轉換成爲時間戳 print(struct_2_stamp) print(time.ctime(struct_2_stamp)) # 返回時間爲「Sat Dec 30 00:00:00 2017」格式 # 將時間戳轉爲字符串格式 print(time.gmtime(time.time() - 86640)) # 將utc時間戳轉換struct_time格式 print(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())) # 將utc struct_time格式轉換成指定的字符串格式 print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) # 將本地 struct_time格式轉換成指定的字符串格式
import datetime print(datetime.datetime.now()) # 返回「2017-12-30 17:56:40.261813」 print(datetime.date.fromtimestamp(time.time())) # 時間戳直接轉換成爲日期格式「2017-12-30」 # 時間加減 print(datetime.datetime.now()) print(datetime.datetime.now() + datetime.timedelta(3)) # 當前時間+3天 print(datetime.datetime.now() + datetime.timedelta(-3)) # 當前時間-3天 print(datetime.datetime.now() + datetime.timedelta(hours=3)) # 當前時間+3小時 print(datetime.datetime.now() + datetime.timedelta(minutes=30)) # 當前時間+30分鐘 c_time = datetime.datetime.now() # print(c_time.replace(minute=3, hour=2)) # 時間替換,替換小時和分鐘 print(c_time.replace(hour=2, minute=3)) # 時間替換,替換小時和分鐘
logging模式是一個日誌模塊,不少程序都須要一個記錄日誌,因此python爲咱們提供了這麼一個模塊,logging的日誌分爲5個等級:debug(),waring(),error(),critical()
日誌等級(數字越大,表示危害越高):
critical = 50
error = 40
warning = 30
info = 20
debug = 10
注意:只有【當前寫等級】大於【日誌等級】時,日誌文件才被記錄
日誌輸出,最簡單的用法:
import logging logging.warning("user [smelond] attempted wrong password more than 3 times") # 能夠直接輸出到屏幕上 logging.critical("server is down")
將日誌輸出到文件裏面:
import logging logging.basicConfig(filename='example.log', level=logging.INFO) # 設置將輸出內容保存到example.log # level=loggin.INFO意思是,把日誌紀錄級別設置爲INFO,也就是說,只有比日誌是INFO或比INFO級別更高的日誌纔會被紀錄到文件裏 logging.debug("this message should go to the log file") # 不會保存到日誌文件裏面 logging.info("So should this") # 日誌級別也爲info,因此能夠保存到文件 logging.warning("And this,too") # 這個等級大於info,因此也能夠保存到文件裏面
將日誌輸出到文件裏面,而且加上時間:
logging.basicConfig(filename='example.log', level=logging.INFO, format="%(asctime)s (message)s", datefmt="%m%d%Y %H:%M:%S %p") # format格式化輸出,後面放時間格式 # level=loggin.INFO意思是,把日誌紀錄級別設置爲INFO,也就是說,只有比日誌是INFO或比INFO級別更高的日誌纔會被紀錄到文件裏 logging.debug("this message should go to the log file") # 不會保存到日誌文件裏面 logging.info("So should this") # 日誌級別也爲info,因此能夠保存到文件 logging.warning("And this,too") # 這個等級大於info,因此也能夠保存到文件裏面 logging.warning("is when this event was logged.") # 大於info 輸出: 01012018 20:16:36 PM So should this 01012018 20:16:36 PM And this,too 01012018 20:16:36 PM is when this event was logged.
如下來自alex li
日誌輸出格式:
%(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將(logging建立)日誌記錄發送到合適的目的輸出
filter提供了細度設備來決定輸出哪條日誌記錄
formatter決定日誌記錄的最終輸出格式
logger
每一個程序在輸出信息以前都要得到一個Logger。Logger一般對應了程序的模塊名,好比聊天工具的圖形界面模塊能夠這樣得到它的Logger:
LOG=logging.getLogger(」chat.gui」)
而核心模塊能夠這樣:
LOG=logging.getLogger(」chat.kernel」)
Logger.setLevel(lel):指定最低的日誌級別,低於lel的級別將被忽略。debug是最低的內置級別,critical爲最高
Logger.addFilter(filt)、Logger.removeFilter(filt):添加或刪除指定的filter
Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增長或刪除指定的handler
Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():能夠設置的日誌級別
handler
handler對象負責發送相關的信息到指定目的地。Python的日誌系統有多種Handler可使用。有些Handler能夠把信息輸出到控制檯,有些Logger能夠把信息輸出到文件,還有些 Handler能夠把信息發送到網絡上。若是以爲不夠用,還能夠編寫本身的Handler。能夠經過addHandler()方法添加多個多handler
Handler.setLevel(lel):指定被處理的信息級別,低於lel級別的信息將被忽略
Handler.setFormatter():給這個handler選擇一個格式
Handler.addFilter(filt)、Handler.removeFilter(filt):新增或刪除一個filter對象
每一個Logger能夠附加多個Handler。接下來咱們就來介紹一些經常使用的Handler:
1) logging.StreamHandler
使用這個Handler能夠向相似與sys.stdout或者sys.stderr的任何文件對象(file object)輸出信息。它的構造函數是:
StreamHandler([strm])
其中strm參數是一個文件對象。默認是sys.stderr
2) logging.FileHandler
和StreamHandler相似,用於向一個文件輸出日誌信息。不過FileHandler會幫你打開這個文件。它的構造函數是:
FileHandler(filename[,mode])
filename是文件名,必須指定一個文件名。
mode是文件的打開方式。參見Python內置函數open()的用法。默認是’a',即添加到文件末尾。
3) logging.handlers.RotatingFileHandler
這個Handler相似於上面的FileHandler,可是它能夠管理文件大小。當文件達到必定大小以後,它會自動將當前日誌文件更名,而後建立 一個新的同名日誌文件繼續輸出。好比日誌文件是chat.log。當chat.log達到指定的大小以後,RotatingFileHandler自動把 文件更名爲chat.log.1。不過,若是chat.log.1已經存在,會先把chat.log.1重命名爲chat.log.2。。。最後從新建立 chat.log,繼續輸出日誌信息。它的構造函數是:
RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
其中filename和mode兩個參數和FileHandler同樣。
maxBytes用於指定日誌文件的最大文件大小。若是maxBytes爲0,意味着日誌文件能夠無限大,這時上面描述的重命名過程就不會發生。
backupCount用於指定保留的備份文件的個數。好比,若是指定爲2,當上面描述的重命名過程發生時,原有的chat.log.2並不會被改名,而是被刪除。
4) logging.handlers.TimedRotatingFileHandler
這個Handler和RotatingFileHandler相似,不過,它沒有經過判斷文件大小來決定什麼時候從新建立日誌文件,而是間隔必定時間就 自動建立新的日誌文件。重命名的過程與RotatingFileHandler相似,不過新的文件不是附加數字,而是當前時間。它的構造函數是:
TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
其中filename參數和backupCount參數和RotatingFileHandler具備相同的意義。
interval是時間間隔。
when參數是一個字符串。表示時間間隔的單位,不區分大小寫。它有如下取值:
S 秒
M 分
H 小時
D 天
W 每星期(interval==0時表明星期一)
midnight 天天凌晨
將日誌文件輸出到多個地方:
# 將日誌輸出到多個地方 import logging # create logger logger = logging.getLogger('TEST-LOG') # 設置一個名稱 logger.setLevel(logging.INFO) # 設置一個最低日誌輸出等級,設置爲了INFO等級,(全局) # create console handler and set level to debug ch = logging.StreamHandler() # 輸出到屏幕上 ch.setLevel(logging.DEBUG) # 設置屏幕輸出的最低日誌等級可是會發現不能輸出debug,由於咱們上面的全局配置上最低設置成爲了INFO等級,DEBIG>INFO # create file handler and set level to warning fh = logging.FileHandler("access.log") # 設置輸出到文件 fh.setLevel(logging.WARNING) # 設置文件輸出的最低等級 # create formatter formatter_ch = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 格式化 formatter_fh = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') # 格式化 # add formatter to ch and fh ch.setFormatter(formatter_ch) # 設置輸出到屏幕上的格式 fh.setFormatter(formatter_fh) # 設置輸出到日誌中的格式 # add ch and fh to logger logger.addHandler(ch) # 添加handler logger.addHandler(fh) # 'application' code logger.debug('debug message') # 輸出提示(不能輸出到任何地方) logger.info('info message') # 輸出提示(只能輸出到屏幕,由於輸出到文件最低等級須要WARNING) logger.warning('warn message') # 輸出提示(雙方) logger.error('error message') # 雙方 logger.critical('critical message') # 雙方 屏幕輸出: 2018-01-02 11:44:34,121 - TEST-LOG - INFO - info message 2018-01-02 11:44:34,121 - TEST-LOG - WARNING - warn message 2018-01-02 11:44:34,121 - TEST-LOG - ERROR - error message 2018-01-02 11:44:34,121 - TEST-LOG - CRITICAL - critical message 文件輸出: 2018-01-02 11:44:34,121 - WARNING - warn message 2018-01-02 11:44:34,121 - ERROR - error message 2018-01-02 11:44:34,121 - CRITICAL - critical message