Python學(xué)習(xí)記錄day5


title: Python學(xué)習(xí)記錄day5
tags: python
author: Chinge Yang
date: 2016-11-26


1.多層裝飾器

多層裝飾器的原理是度陆,裝飾器裝飾函數(shù)后哗总,其實(shí)也是一個(gè)函數(shù)夹纫,這樣又可以被裝飾器裝飾栖忠。 編譯是從下至上進(jìn)行的崔挖,執(zhí)行時(shí)是從上至下進(jìn)行贸街。

#!/usr/bin/env python
# _*_coding:utf-8_*_
'''
 * Created on 2016/11/29 20:38.
 * @author: Chinge_Yang.
'''

USER_INFO = {}


# USER_INFO['is_login'] = True
# USER_INFO['user_type'] = 2


def check_login(func):
    def inner(*args, **kwargs):
        if USER_INFO.get("is_login", None):
            ret = func(*args, **kwargs)
            return ret
        else:
            print("請(qǐng)登錄")

    return inner


def check_admin(func):
    def inner(*args, **kwargs):
        if USER_INFO.get('user_type', None) == 2:
            ret = func(*args, **kwargs)
            return ret
        else:
            print('無(wú)權(quán)限查看')

    return inner


@check_login
@check_admin
def index():
    """
    管理員的功能
    :return:
    """
    print('Index')


@check_login
def home():
    """
    普通用戶功能
    :return:
    """
    print("home")


def login():
    user = input("請(qǐng)輸入用戶名:")
    if user == "admin":
        USER_INFO["is_login"] = True
        USER_INFO["user_type"] = 2
    else:
        USER_INFO["is_login"] = True
        USER_INFO["user_type"] = 1


def main():
    while True:
        inp = input("1.登錄;2.查看信息狸相;3.超級(jí)管理員管理\n >>>")
        if inp == "1":
            login()
        elif inp == "2":
            home()
        elif inp == "3":
            index()
        elif inp == "q":
            exit()


main()

2.字符串格式化

Python的字符串格式化有兩種方式: 百分號(hào)方式薛匪、format方式

百分號(hào)的方式相對(duì)來(lái)說(shuō)比較老,而format方式則是比較先進(jìn)的方式脓鹃,企圖替換古老的方式逸尖,目前兩者并存。[PEP-3101]
This PEP proposes a new system for built-in string formatting operations, intended as a replacement for the existing '%' string formatting operator.

1.百分號(hào)方式

%[(name)][flags][width].[precision]typecode

  • (name) 可選将谊,用于選擇指定的key
  • flags 可選冷溶,可供選擇的值有:
    + 右對(duì)齊;正數(shù)前加正好尊浓,負(fù)數(shù)前加負(fù)號(hào)逞频;
    - 左對(duì)齊;正數(shù)前無(wú)符號(hào)栋齿,負(fù)數(shù)前加負(fù)號(hào)苗胀;
    空格 右對(duì)齊;正數(shù)前加空格瓦堵,負(fù)數(shù)前加負(fù)號(hào)基协;
    0 右對(duì)齊;正數(shù)前無(wú)符號(hào)菇用,負(fù)數(shù)前加負(fù)號(hào)澜驮;用0填充空白處
  • width 可選,占有寬度
  • .precision 可選惋鸥,小數(shù)點(diǎn)后保留的位數(shù)
  • typecode 必選
    s杂穷,獲取傳入對(duì)象的str方法的返回值,并將其格式化到指定位置
    r卦绣,獲取傳入對(duì)象的repr方法的返回值耐量,并將其格式化到指定位置
    c,整數(shù):將數(shù)字轉(zhuǎn)換成其unicode對(duì)應(yīng)的值滤港,10進(jìn)制范圍為 0 <= i <= 1114111(py27則只支持0-255)廊蜒;字符:將字符添加到指定位置
    o,將整數(shù)轉(zhuǎn)換成 八 進(jìn)制表示溅漾,并將其格式化到指定位置
    x山叮,將整數(shù)轉(zhuǎn)換成十六進(jìn)制表示添履,并將其格式化到指定位置
    d缝龄,將整數(shù)汰现、浮點(diǎn)數(shù)轉(zhuǎn)換成 十 進(jìn)制表示叔壤,并將其格式化到指定位置
    E,將整數(shù)炼绘、浮點(diǎn)數(shù)轉(zhuǎn)換成科學(xué)計(jì)數(shù)法嗅战,并將其格式化到指定位置(大寫E)
    f, 將整數(shù)驮捍、浮點(diǎn)數(shù)轉(zhuǎn)換成浮點(diǎn)數(shù)表示东且,并將其格式化到指定位置(默認(rèn)保留小數(shù)點(diǎn)后6位)
    F本讥,同上
    g拷沸,自動(dòng)調(diào)整將整數(shù)撞芍、浮點(diǎn)數(shù)轉(zhuǎn)換成浮點(diǎn)型或科學(xué)計(jì)數(shù)法表示(超過(guò)6位數(shù)用科學(xué)計(jì)數(shù)法),并將其格式化到指定位置(如果是科學(xué)計(jì)數(shù)則是e验毡;)
    G米罚,自動(dòng)調(diào)整將整數(shù)录择、浮點(diǎn)數(shù)轉(zhuǎn)換成浮點(diǎn)型或科學(xué)計(jì)數(shù)法表示(超過(guò)6位數(shù)用科學(xué)計(jì)數(shù)法)碗降,并將其格式化到指定位置(如果是科學(xué)計(jì)數(shù)則是E讼渊;)
    %爪幻,當(dāng)字符串中存在格式化標(biāo)志時(shí)须误,需要用 %%表示一個(gè)百分號(hào)

注:Python中百分號(hào)格式化是不存在自動(dòng)將整數(shù)轉(zhuǎn)換成二進(jìn)制表示的方式

常用格式化:

tpl = "i am %s" % "ygqygq2"
 
tpl = "i am %s age %d" % ("ygqygq2", 27)
 
tpl = "i am %(name)s age %(age)d" % {"name": "ygqgyq2", "age": 27}
 
tpl = "percent %.2f" % 99.97623
 
tpl = "i am %(pp).2f" % {"pp": 123.425556, }
 
tpl = "i am %.2f %%" % {"pp": 123.425556, }

2.Format方式

[[fill]align][sign][#][0][width][,][.precision][type]

  • fill 【可選】空白處填充的字符
  • align 【可選】對(duì)齊方式(需配合width使用)
    <京痢,內(nèi)容左對(duì)齊
    >祭椰,內(nèi)容右對(duì)齊(默認(rèn))
    =方淤,內(nèi)容右對(duì)齊携茂,將符號(hào)放置在填充字符的左側(cè)邑蒋,且只對(duì)數(shù)字類型有效按厘。即使:符號(hào)+填充物+數(shù)字
    ^逮京,內(nèi)容居中
    sign 【可選】有無(wú)符號(hào)數(shù)字
    +懒棉,正號(hào)加正策严,負(fù)號(hào)加負(fù)妻导;
    -,正號(hào)不變术浪,負(fù)號(hào)加負(fù)胰苏;
    空格 硕并,正號(hào)空格倔毙,負(fù)號(hào)加負(fù)普监;
    # 【可選】對(duì)于二進(jìn)制琉兜、八進(jìn)制、十六進(jìn)制豌蟋,如果加上#梧疲,會(huì)顯示0b/0o/0x,否則不顯示
    缭受, 【可選】為數(shù)字添加分隔符米者,如:1,000,000
    width 【可選】格式化位所占寬度
    .precision 【可選】小數(shù)位保留精度
    type 【可選】格式化類型
    傳入” 字符串類型 “的參數(shù)
    s蔓搞,格式化字符串類型數(shù)據(jù)
    空白喂分,未指定類型蒲祈,則默認(rèn)是None蜒车,同s
    傳入“ 整數(shù)類型 ”的參數(shù)
    b酿愧,將10進(jìn)制整數(shù)自動(dòng)轉(zhuǎn)換成2進(jìn)制表示然后格式化
    c嬉挡,將10進(jìn)制整數(shù)自動(dòng)轉(zhuǎn)換為其對(duì)應(yīng)的unicode字符
    d,十進(jìn)制整數(shù)
    o因谎,將10進(jìn)制整數(shù)自動(dòng)轉(zhuǎn)換成8進(jìn)制表示然后格式化财岔;
    x匠璧,將10進(jìn)制整數(shù)自動(dòng)轉(zhuǎn)換成16進(jìn)制表示然后格式化(小寫x)
    X夷恍,將10進(jìn)制整數(shù)自動(dòng)轉(zhuǎn)換成16進(jìn)制表示然后格式化(大寫X)
    傳入“ 浮點(diǎn)型或小數(shù)類型 ”的參數(shù)
    e酿雪, 轉(zhuǎn)換為科學(xué)計(jì)數(shù)法(小寫e)表示指黎,然后格式化州丹;
    E当叭, 轉(zhuǎn)換為科學(xué)計(jì)數(shù)法(大寫E)表示蚁鳖,然后格式化;
    f 醉箕, 轉(zhuǎn)換為浮點(diǎn)型(默認(rèn)小數(shù)點(diǎn)后保留6位)表示讥裤,然后格式化己英;
    F, 轉(zhuǎn)換為浮點(diǎn)型(默認(rèn)小數(shù)點(diǎn)后保留6位)表示荣瑟,然后格式化笆焰;
    g嚷掠, 自動(dòng)在e和f中切換
    G叠国, 自動(dòng)在E和F中切換
    %戴尸,顯示百分比(默認(rèn)顯示小數(shù)點(diǎn)后6位)

常用格式化:

tpl = "i am {}, age {}, {}".format("seven", 18, 'alex')
  
tpl = "i am {}, age {}, {}".format(*["seven", 18, 'alex'])
  
tpl = "i am {0}, age {1}, really {0}".format("seven", 18)
  
tpl = "i am {0}, age {1}, really {0}".format(*["seven", 18])
  
tpl = "i am {name}, age {age}, really {name}".format(name="seven", age=18)
  
tpl = "i am {name}, age {age}, really {name}".format(**{"name": "seven", "age": 18})
  
tpl = "i am {0[0]}, age {0[1]}, really {0[2]}".format([1, 2, 3], [11, 22, 33])
  
tpl = "i am {:s}, age {:d}, money {:f}".format("seven", 18, 88888.1)
  
tpl = "i am {:s}, age {:d}".format(*["seven", 18])
  
tpl = "i am {name:s}, age {age:d}".format(name="seven", age=18)
  
tpl = "i am {name:s}, age {age:d}".format(**{"name": "seven", "age": 18})
 
tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2)
 
tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2)
 
tpl = "numbers: {0:b},{0:o},{0:d},{0:x},{0:X}, {0:%}".format(15)
 
tpl = "numbers: {num:b},{num:o},{num:d},{num:x},{num:X}, {num:%}".format(num=15)

更多格式化操作:https://docs.python.org/3/library/string.html

3.迭代器和生成器

1.迭代器

迭代器是訪問(wèn)集合元素的一種方式。迭代器對(duì)象從集合的第一個(gè)元素開(kāi)始訪問(wèn)挎峦,直到所有的元素被訪問(wèn)完結(jié)束坦胶。迭代器只能往前不會(huì)后退顿苇,不過(guò)這也沒(méi)什么纪岁,因?yàn)槿藗兒苌僭诘局型笸酸:病A硗庖旁觯鞯囊淮髢?yōu)點(diǎn)是不要求事先準(zhǔn)備好整個(gè)迭代過(guò)程中所有的元素做修。迭代器僅僅在迭代到某個(gè)元素時(shí)才計(jì)算該元素缓待,而在這之前或之后旋炒,元素可以不存在或者被銷毀瘫镇。這個(gè)特點(diǎn)使得它特別適合用于遍歷一些巨大的或是無(wú)限的集合铣除,比如幾個(gè)G的文件

特點(diǎn):

訪問(wèn)者不需要關(guān)心迭代器內(nèi)部的結(jié)構(gòu)尚粘,僅需通過(guò)next()方法不斷去取下一個(gè)內(nèi)容
不能隨機(jī)訪問(wèn)集合中的某個(gè)值 郎嫁,只能從頭到尾依次訪問(wèn)
訪問(wèn)到一半時(shí)不能往回退
便于循環(huán)比較大的數(shù)據(jù)集合泽铛,節(jié)省內(nèi)存

>>> a = iter([1,2,3,4,5])
>>> a
<list_iterator object at 0x101402630>
>>> a.__next__()
1
>>> a.__next__()
2
>>> a.__next__()
3
>>> a.__next__()
4
>>> a.__next__()
5
>>> a.__next__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

2.生成器

一個(gè)函數(shù)調(diào)用時(shí)返回一個(gè)迭代器杠茬,那這個(gè)函數(shù)就叫做生成器(generator)瓢喉;如果函數(shù)中包含yield語(yǔ)法灯荧,那這個(gè)函數(shù)就會(huì)變成生成器逗载;

def func():
    print(11)
    yield 1
    print(22)
    yield 2
    print(33)
    yield 3
    print(44)
    yield 4

上述代碼中:func是函數(shù)稱為生成器厉斟,當(dāng)執(zhí)行此函數(shù)func()時(shí)會(huì)得到一個(gè)迭代器擦秽。

>>> temp = func()
>>> temp.__next__()
11
1
>>> temp.__next__()
22
2
>>> temp.__next__()
33
3
>>> temp.__next__()
44
4
>>> temp.__next__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

4.函數(shù)遞歸

在函數(shù)內(nèi)部感挥,可以調(diào)用其他函數(shù)触幼。如果一個(gè)函數(shù)在內(nèi)部調(diào)用自身本身置谦,這個(gè)函數(shù)就是遞歸函數(shù)媒峡。

def func(n):
    n += 1
    if n >= 4:
        return "end"
    return func(n)

res = func(1)
print(res)

遞歸函數(shù)的優(yōu)點(diǎn)是定義簡(jiǎn)單半哟,邏輯清晰寓涨。理論上贱田,所有的遞歸函數(shù)都可以寫成循環(huán)的方式,但循環(huán)的邏輯不如遞歸清晰耗拓。

使用遞歸函數(shù)需要注意防止棧溢出乔询。

詳細(xì)請(qǐng)看廖雪峰的官方網(wǎng)站中遞歸函數(shù)

5.模塊

為了編寫可維護(hù)的代碼竿刁,我們把很多函數(shù)分組食拜,分別放到不同的文件里负甸,這樣呻待,每個(gè)文件包含的代碼就相對(duì)較少蚕捉,很多編程語(yǔ)言都采用這種組織代碼的方式鱼冀。在Python中千绪,一個(gè).py文件就稱之為一個(gè)模塊(Module)盹靴。
模塊分為三種:
* 自定義模塊
* 第三方模塊
* 內(nèi)置模塊

1.使用模塊有什么好處稿静?

1. 最大的好處是大大提高了代碼的可維護(hù)性改备。
2. 使用模塊還可以避免函數(shù)名和變量名沖突悬钳。

2.導(dǎo)入模塊

單模塊:import
嵌套在文件夾下:
from xxx import xxx
from xxx import as ooo

3.第三方模塊

pip3安裝(pip安裝)
pip3 install requests
源碼安裝
curl -OL https://github.com/kennethreitz/requests/tarball/master

解壓后,進(jìn)入目錄

python setup.py install

6.序列化

Python中用于序列化的兩個(gè)模塊

  • json 用于【字符串】和【python基本數(shù)據(jù)類型】間進(jìn)行轉(zhuǎn)換
  • pickle 用于【python特有的類型】和【python基本數(shù)據(jù)類型】間進(jìn)行轉(zhuǎn)換

Json模塊提供了四個(gè)功能:dumps母剥、dump环疼、loads秦爆、load
pickle模塊提供了四個(gè)功能:dumps等限、dump形娇、loads桐早、load

json相關(guān)用法:

import json

dict = {'k1': 'v1'}
print(dict, type(dict))
# 將python基本數(shù)據(jù)類型轉(zhuǎn)換成字符串形式
res = json.dumps(dict)
print(res, type(res))

{'k1': 'v1'} <class 'dict'>
{"k1": "v1"} <class 'str'>

import json

# 將python字符串形式轉(zhuǎn)換成基本數(shù)據(jù)類型
s1 = '{"k1": 123}'
dict = json.loads(s1)   # 反序列化時(shí),一定要使用 ""
print(dict, type(dict))

{'k1': 123} <class 'dict'>

import json

li = [11,22,33]
json.dump(li,open('test.txt','w'))

li = json.load(open('test.txt','r'))
print(type(li),li)

pickle相關(guān)用法:

import pickle

li = [11,22,33]
r = pickle.dumps(li)
print(r)

res = pickle.loads(r)
print(res)

b'\x80\x03]q\x00(K\x0bK\x16K!e.'
[11, 22, 33]

li = [11,22,33]
pickle.dump(li, open('test4.txt', 'wb'))

res = pickle.load(open('test4.txt', 'rb'))
print(res)

[11, 22, 33]

json和pickle對(duì)比:
1. json更適合跨語(yǔ)言陶衅,字符串搀军,基本數(shù)據(jù)類型
2. pickle更適合python所有類型的序列化操作

7.time & datetime模塊

#_*_coding:utf-8_*_
__author__ = 'Alex Li'

import time


# print(time.clock()) #返回處理器時(shí)間,3.3開(kāi)始已廢棄 , 改成了time.process_time()測(cè)量處理器運(yùn)算時(shí)間,不包括sleep時(shí)間,不穩(wěn)定,mac上測(cè)不出來(lái)
# print(time.altzone)  #返回與utc時(shí)間的時(shí)間差,以秒計(jì)算\
# print(time.asctime()) #返回時(shí)間格式"Fri Aug 19 11:14:16 2016",
# print(time.localtime()) #返回本地時(shí)間 的struct time對(duì)象格式
# print(time.gmtime(time.time()-800000)) #返回utc時(shí)間的struc時(shí)間對(duì)象格式

# print(time.asctime(time.localtime())) #返回時(shí)間格式"Fri Aug 19 11:14:16 2016",
#print(time.ctime()) #返回Fri Aug 19 12:38:29 2016 格式, 同上



# 日期字符串 轉(zhuǎn)成  時(shí)間戳
# string_2_struct = time.strptime("2016/05/22","%Y/%m/%d") #將 日期字符串 轉(zhuǎn)成 struct時(shí)間對(duì)象格式
# print(string_2_struct)
# #
# struct_2_stamp = time.mktime(string_2_struct) #將struct時(shí)間對(duì)象轉(zhuǎn)成時(shí)間戳
# print(struct_2_stamp)



#將時(shí)間戳轉(zhuǎn)為字符串格式
# print(time.gmtime(time.time()-86640)) #將utc時(shí)間戳轉(zhuǎn)換成struct_time格式
# print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) #將utc struct_time格式轉(zhuǎn)成指定的字符串格式





#時(shí)間加減
import datetime

# print(datetime.datetime.now()) #返回 2016-08-19 12:47:03.941925
#print(datetime.date.fromtimestamp(time.time()) )  # 時(shí)間戳直接轉(zhuǎn)成日期格式 2016-08-19
# print(datetime.datetime.now() )
# print(datetime.datetime.now() + datetime.timedelta(3)) #當(dāng)前時(shí)間+3天
# print(datetime.datetime.now() + datetime.timedelta(-3)) #當(dāng)前時(shí)間-3天
# print(datetime.datetime.now() + datetime.timedelta(hours=3)) #當(dāng)前時(shí)間+3小時(shí)
# print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #當(dāng)前時(shí)間+30分


#
# c_time  = datetime.datetime.now()
# print(c_time.replace(minute=3,hour=2)) #時(shí)間替換

8.logging模塊

很多程序都有記錄日志的需求敛摘,并且日志中包含的信息即有正常的程序訪問(wèn)日志兄淫,還可能有錯(cuò)誤拖叙、警告等信息輸出,python的logging模塊提供了標(biāo)準(zhǔn)的日志接口挖滤,你可以通過(guò)它存儲(chǔ)各種格式的日志,logging的日志可以分為 debug(), info(), warning(), error() and critical() 5個(gè)級(jí)別浅役,下面我們看一下怎么用斩松。
最簡(jiǎn)單用法

import logging
 
logging.warning("user [alex] attempted wrong password more than 3 times")
logging.critical("server is down")

WARNING:root:user [alex] attempted wrong password more than 3 times
CRITICAL:root:server is down

Level When it’s used
DEBUG Detailed information, typically of interest only when diagnosing problems.
INFO Confirmation that things are working as expected.
WARNING An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected.
ERROR Due to a more serious problem, the software has not been able to perform some function.
CRITICAL A serious error, indicating that the program itself may be unable to continue running.

看一下這幾個(gè)日志級(jí)別分別代表什么意思

Level When it’s used
DEBUG Detailed information, typically of interest only when diagnosing problems.
INFO Confirmation that things are working as expected.
WARNING An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected.
ERROR Due to a more serious problem, the software has not been able to perform some function.
CRITICAL A serious error, indicating that the program itself may be unable to continue running.

如果想把日志寫到文件里,也很簡(jiǎn)單

import logging
 
logging.basicConfig(filename='example.log',level=logging.?INFO)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')

其中下面這句中的level=loggin.INFO意思是觉既,把日志紀(jì)錄級(jí)別設(shè)置為INFO惧盹,也就是說(shuō)乳幸,只有比日志是INFO或比INFO級(jí)別更高的日志才會(huì)被紀(jì)錄到文件里钧椰,在這個(gè)例子粹断, 第一條日志是不會(huì)被紀(jì)錄的,如果希望紀(jì)錄debug的日志嫡霞,那把日志級(jí)別改成DEBUG就行了瓶埋。

logging.basicConfig(filename='example.log',level=logging.INFO)

感覺(jué)上面的日志格式忘記加上時(shí)間啦,日志不知道時(shí)間怎么行呢诊沪,下面就來(lái)加上!

import logging
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')

12/12/2010 11:46:36 AM is when this event was logged.

%(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 用戶輸出的消息

日志格式

%(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 用戶輸出的消息

如果想同時(shí)把log打印在屏幕和文件日志里,就需要了解一點(diǎn)復(fù)雜的知識(shí) 了

Python 使用logging模塊記錄日志涉及四個(gè)主要類怠晴,使用官方文檔中的概括最為合適:
1. logger提供了應(yīng)用程序可以直接使用的接口遥金;
2. handler將(logger創(chuàng)建的)日志記錄發(fā)送到合適的目的輸出;
3. filter提供了細(xì)度設(shè)備來(lái)決定輸出哪條日志記錄蒜田;
4. formatter決定日志記錄的最終輸出格式稿械。

logger
每個(gè)程序在輸出信息之前都要獲得一個(gè)Logger。Logger通常對(duì)應(yīng)了程序的模塊名冲粤,比如聊天工具的圖形界面模塊可以這樣獲得它的Logger:
LOG=logging.getLogger(”chat.gui”)
而核心模塊可以這樣:
LOG=logging.getLogger(”chat.kernel”)

Logger.setLevel(lel):指定最低的日志級(jí)別美莫,低于lel的級(jí)別將被忽略页眯。debug是最低的內(nèi)置級(jí)別,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():可以設(shè)置的日志級(jí)別

handler
handler對(duì)象負(fù)責(zé)發(fā)送相關(guān)的信息到指定目的地蝌矛。Python的日志系統(tǒng)有多種Handler可以使用道批。有些Handler可以把信息輸出到控制臺(tái),有些Logger可以把信息輸出到文件入撒,還有些 Handler可以把信息發(fā)送到網(wǎng)絡(luò)上隆豹。如果覺(jué)得不夠用,還可以編寫自己的Handler茅逮×模可以通過(guò)addHandler()方法添加多個(gè)多handler
Handler.setLevel(lel):指定被處理的信息級(jí)別,低于lel級(jí)別的信息將被忽略
Handler.setFormatter():給這個(gè)handler選擇一個(gè)格式
Handler.addFilter(filt)献雅、Handler.removeFilter(filt):新增或刪除一個(gè)filter對(duì)象

每個(gè)Logger可以附加多個(gè)Handler碉考。接下來(lái)我們就來(lái)介紹一些常用的Handler:

  1. logging.StreamHandler
    使用這個(gè)Handler可以向類似與sys.stdout或者sys.stderr的任何文件對(duì)象(file object)輸出信息。它的構(gòu)造函數(shù)是:
    StreamHandler([strm])
    其中strm參數(shù)是一個(gè)文件對(duì)象挺身。默認(rèn)是sys.stderr
  2. logging.FileHandler
    和StreamHandler類似侯谁,用于向一個(gè)文件輸出日志信息。不過(guò)FileHandler會(huì)幫你打開(kāi)這個(gè)文件章钾。它的構(gòu)造函數(shù)是:
    FileHandler(filename[,mode])
    filename是文件名墙贱,必須指定一個(gè)文件名。
    mode是文件的打開(kāi)方式贱傀。參見(jiàn)Python內(nèi)置函數(shù)open()的用法惨撇。默認(rèn)是’a',即添加到文件末尾府寒。
  3. logging.handlers.RotatingFileHandler
    這個(gè)Handler類似于上面的FileHandler魁衙,但是它可以管理文件大小。當(dāng)文件達(dá)到一定大小之后椰棘,它會(huì)自動(dòng)將當(dāng)前日志文件改名纺棺,然后創(chuàng)建 一個(gè)新的同名日志文件繼續(xù)輸出榄笙。比如日志文件是chat.log邪狞。當(dāng)chat.log達(dá)到指定的大小之后,RotatingFileHandler自動(dòng)把 文件改名為chat.log.1茅撞。不過(guò)帆卓,如果chat.log.1已經(jīng)存在巨朦,會(huì)先把chat.log.1重命名為chat.log.2。剑令。糊啡。最后重新創(chuàng)建 chat.log,繼續(xù)輸出日志信息吁津。它的構(gòu)造函數(shù)是:
    RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
    其中filename和mode兩個(gè)參數(shù)和FileHandler一樣棚蓄。
    maxBytes用于指定日志文件的最大文件大小。如果maxBytes為0碍脏,意味著日志文件可以無(wú)限大梭依,這時(shí)上面描述的重命名過(guò)程就不會(huì)發(fā)生。
    backupCount用于指定保留的備份文件的個(gè)數(shù)典尾。比如役拴,如果指定為2,當(dāng)上面描述的重命名過(guò)程發(fā)生時(shí)钾埂,原有的chat.log.2并不會(huì)被更名河闰,而是被刪除。
  4. logging.handlers.TimedRotatingFileHandler
    這個(gè)Handler和RotatingFileHandler類似褥紫,不過(guò)姜性,它沒(méi)有通過(guò)判斷文件大小來(lái)決定何時(shí)重新創(chuàng)建日志文件,而是間隔一定時(shí)間就 自動(dòng)創(chuàng)建新的日志文件髓考。重命名的過(guò)程與RotatingFileHandler類似污抬,不過(guò)新的文件不是附加數(shù)字,而是當(dāng)前時(shí)間绳军。它的構(gòu)造函數(shù)是:
    TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
    其中filename參數(shù)和backupCount參數(shù)和RotatingFileHandler具有相同的意義印机。
    interval是時(shí)間間隔。
    when參數(shù)是一個(gè)字符串门驾。表示時(shí)間間隔的單位射赛,不區(qū)分大小寫。它有以下取值:
    S 秒
    M 分
    H 小時(shí)
    D 天
    W 每星期(interval==0時(shí)代表星期一)
    midnight 每天凌晨
import logging
 
#create logger
logger = logging.getLogger('TEST-LOG')
logger.setLevel(logging.DEBUG)
 
 
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
 
# create file handler and set level to warning
fh = logging.FileHandler("access.log")
fh.setLevel(logging.WARNING)
# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
 
# add formatter to ch and fh
ch.setFormatter(formatter)
fh.setFormatter(formatter)
 
# add ch and fh to logger
logger.addHandler(ch)
logger.addHandler(fh)
 
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
import logging

from logging import handlers

logger = logging.getLogger(__name__)

log_file = "timelog.log"
#fh = handlers.RotatingFileHandler(filename=log_file,maxBytes=10,backupCount=3)
fh = handlers.TimedRotatingFileHandler(filename=log_file,when="S",interval=5,backupCount=3)


formatter = logging.Formatter('%(asctime)s %(module)s:%(lineno)d %(message)s')

fh.setFormatter(formatter)

logger.addHandler(fh)


logger.warning("test1")
logger.warning("test12")
logger.warning("test13")
logger.warning("test14")
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末奶是,一起剝皮案震驚了整個(gè)濱河市楣责,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌聂沙,老刑警劉巖秆麸,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異及汉,居然都是意外死亡沮趣,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門坷随,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)房铭,“玉大人驻龟,你說(shuō)我怎么就攤上這事「追耍” “怎么了翁狐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)凌蔬。 經(jīng)常有香客問(wèn)我露懒,道長(zhǎng),這世上最難降的妖魔是什么砂心? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任隐锭,我火速辦了婚禮,結(jié)果婚禮上计贰,老公的妹妹穿的比我還像新娘钦睡。我一直安慰自己,他們只是感情好躁倒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布荞怒。 她就那樣靜靜地躺著,像睡著了一般秧秉。 火紅的嫁衣襯著肌膚如雪褐桌。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,727評(píng)論 1 305
  • 那天象迎,我揣著相機(jī)與錄音荧嵌,去河邊找鬼。 笑死砾淌,一個(gè)胖子當(dāng)著我的面吹牛啦撮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播汪厨,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼赃春,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了劫乱?” 一聲冷哼從身側(cè)響起织中,我...
    開(kāi)封第一講書(shū)人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎衷戈,沒(méi)想到半個(gè)月后狭吼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡殖妇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年刁笙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡采盒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蔚润,到底是詐尸還是另有隱情磅氨,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布嫡纠,位于F島的核電站烦租,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏除盏。R本人自食惡果不足惜叉橱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望者蠕。 院中可真熱鬧窃祝,春花似錦、人聲如沸踱侣。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)抡句。三九已至探膊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間待榔,已是汗流浹背逞壁。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锐锣,地道東北人腌闯。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像雕憔,于是被迫代替她去往敵國(guó)和親绑嘹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Day05的課程要點(diǎn)記錄詳細(xì)教程地址:Day5 - 常用模塊學(xué)習(xí) | 第四篇:模塊 一橘茉、模塊介紹 1.1 定義 模...
    乘風(fēng)逐月閱讀 447評(píng)論 0 1
  • 寫在前面的話 代碼中的# > 表示的是輸出結(jié)果 輸入 使用input()函數(shù) 用法 注意input函數(shù)輸出的均是字...
    FlyingLittlePG閱讀 2,764評(píng)論 0 8
  • logging模塊介紹: logging是python內(nèi)置的標(biāo)準(zhǔn)庫(kù)模塊工腋,模塊提供不同的日志級(jí)別,并可以采用不同的方...
    4ffde5305e8f閱讀 2,837評(píng)論 0 2
  • 在現(xiàn)實(shí)生活中畅卓,記錄日志非常重要擅腰。銀行轉(zhuǎn)賬時(shí)會(huì)有轉(zhuǎn)賬記錄;飛機(jī)飛行過(guò)程中翁潘,會(huì)有黑盒子(飛行數(shù)據(jù)記錄器)記錄飛行過(guò)程中...
    chliar閱讀 767評(píng)論 1 0
  • 常用模塊 認(rèn)識(shí)模塊 什么是模塊 什么是模塊? 常見(jiàn)的場(chǎng)景:一個(gè)模塊就是一個(gè)包含了python定義和聲明的文件渗勘,文...
    go以恒閱讀 1,953評(píng)論 0 6