国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Python中使用logging模塊代替print(logging簡明指南)

2019-11-25 18:20:13
字體:
來源:轉載
供稿:網友

替換print?print怎么了?

print 可能是所有學習Python語言的人第一個接觸的東西。它最主要的功能就是往控制臺 打印一段信息,像這樣:

復制代碼 代碼如下:

print 'Hello, logging!'

print也是絕大多數人用來調試自己的程序用的最多的東西,就像寫js使用 console.log 一樣那么自然。很多剛剛開始學習Python的新手甚至有一定經驗的老手,都在使用print 來調試他們的代碼。

比如這是一個我寫的輸出 斐波那契數列 的小程序,讓我們來看看它的代碼:

復制代碼 代碼如下:

# -*- coding: utf-8 -*-
"""
A simple fibonacci program
"""
import argparse

parser = argparse.ArgumentParser(description='I print fibonacci sequence')
parser.add_argument('-s', '--start', type=int, dest='start',
                    help='Start of the sequence', required=True)
parser.add_argument('-e', '--end', type=int, dest='end',
                    help='End of the sequence', required=True)

def infinite_fib():
    a, b = 0, 1
    yield a
    yield b
    while True:
        #print 'Before caculation: a, b = %s, %s' % (a, b)
        a, b = b, a + b
        #print 'After caculation: a, b = %s, %s' % (a, b)
        yield b


def fib(start, end):
    for cur in infinite_fib():
        #print 'cur: %s, start: %s, end: %s' % (cur, start, end)
        if cur > end:
            return
        if cur >= start:
            #print 'Returning result %s' % cur
            yield cur

def main():
    args = parser.parse_args()
    for n in fib(args.start, args.end):
        print n,

if __name__ == '__main__':
    main()


讓我們來看看它工作的怎么樣:

復制代碼 代碼如下:

$ python fib.py  -s 1 -e 100
1 1 2 3 5 8 13 21 34 55 89
$ python fib.py  -s 100 -e 1000
144 233 377 610 987

沒有任何問題,程序正確的完成了它的功能。但等等, 程序里面的那一堆被注釋掉的print語句是怎么回事?

原來,這是我編寫這個小程序的過程中,用來 調試(DEBUG) 的輸出信息,在我完成了這 個程序以后,我自然就把這些print給注釋掉了。讓我們來看看如果把這個print語句打開后結果會怎么樣?

復制代碼 代碼如下:

$ python fib.py  -s 1 -e 100
cur: 0, start: 1, end: 100
cur: 1, start: 1, end: 100
Returning result 1
1 Before caculation: a, b = 0, 1
After caculation: a, b = 1, 1
cur: 1, start: 1, end: 100
... ...
... ...
(不計其數的輸出信息)

如你所見,所有的計算過程都被打印出來了。

寫的時候加上print,提交代碼的時候還得記得把print語句刪掉/注釋掉,為什么我們要忍受這樣的麻煩事呢? 讓我們來介紹我們的主角 logging ,它幾乎就是為這種使用情景而生的。

更好的做法,使用logging模塊

logging模塊是Python內置的日志模塊,使用它可以非常輕松的處理和管理日志輸出。 logging模塊最簡單的用法,是直接使用basicConfig方法來對logging進行配置:

復制代碼 代碼如下:

import logging

# 設置默認的level為DEBUG
# 設置log的格式
logging.basicConfig(
    level=logging.DEBUG,
    format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s"
)

# 記錄log
logging.debug(...)
logging.info(...)
logging.warn(...)
logging.error(...)
logging.critical(...)


這樣配置完logging以后,然后使用``logging.debug``來替換所有的print語句就可以了。 我們會看到這樣的輸出:

復制代碼 代碼如下:

[2014-03-18 15:17:45,216] root:cur: 0, start: 1, end: 100
[2014-03-18 15:17:45,216] root:DEBUG: cur: 1, start: 1, end: 100
[2014-03-18 15:17:45,216] root:DEBUG: Returning result 1
[2014-03-18 15:17:45,216] root:DEBUG: Before caculation: a, b = 0, 1
... ...

使用真正的logger

上面說的basicConfig方法可以滿足你在絕大多數場景下的使用需求,但是basicConfig有一個 很大的缺點。

調用basicConfig其實是給root logger添加了一個handler,這樣當你的程序和別的使用了 logging的第三方模塊一起工作時,會影響第三方模塊的logger行為。這是由logger的繼承特性決定的。

所以我們需要使用真正的logger:

復制代碼 代碼如下:

import logging

# 使用一個名字為fib的logger
logger = logging.getLogger('fib')

# 設置logger的level為DEBUG
logger.setLevel(logging.DEBUG)

# 創建一個輸出日志到控制臺的StreamHandler
hdr = logging.StreamHandler()
formatter = logging.Formatter('[%(asctime)s] %(name)s:%(levelname)s: %(message)s')
hdr.setFormatter(formatter)

# 給logger添加上handler
logger.addHandler(hdr)

這樣再使用logger來進行日志輸出就行了。不過這樣的壞處就是代碼量比basicConfig要大不少。 所以我建議如果是非常簡單的小腳本的話,直接使用basicConfig就可以,如果是稍微大一些 項目,建議認真配置好logger。

動態控制腳本的所有輸出

使用了logging模塊以后,通過修改logger的log level,我們就可以方便的控制程序的輸出了。 比如我們可以為我們的斐波那契數列添加一個 -v 參數,來控制打印所有的調試信息。

復制代碼 代碼如下:

# 添加接收一個verbose參數
parser.add_argument('-v', '--verbose', action='store_true', dest='verbose',
                    help='Enable debug info')

# 判斷verbose
if args.verbose:
    logger.setLevel(logging.DEBUG)
else:
    logger.setLevel(logging.ERROR)

這樣,默認情況下,我們的小程序是不會打印調試信息的,只有當傳入`-v/--verbose`的時候, 我們才會打印出額外的debug信息,就像這樣:

復制代碼 代碼如下:

$ python fib.py  -s 1 -e 100
1 1 2 3 5 8 13 21 34 55 89

$ python fib.py  -s 1 -e 100 -v
[2014-03-18 15:17:45,216] fib:DEBUG: cur: 0, start: 1, end: 100
[2014-03-18 15:17:45,216] fib:DEBUG: cur: 1, start: 1, end: 100
[2014-03-18 15:17:45,216] fib:DEBUG: Returning result 1
[2014-03-18 15:17:45,216] fib:DEBUG: Before caculation: a, b = 0, 1
... ...

如你所見,使用了logging以后,什么時候需要打印DEBUG信息,什么時候需要關閉, 一切變的無比簡單。

所以,趕緊用logging替換掉你的腳本里的print吧!

延伸閱讀

以上這些只是介紹了logging模塊最簡單的一些功能,作為print的替代品來使用,logging 模塊還有很多非常強大好用的功能,比如從文件讀取配置、各種各樣的Handlers等等。 建議閱讀一下logging的官方文檔:

1.logging Logging facility for Python
2.Logging HOWTO

最后附上使用logging模塊的斐波那契數列程序完整代碼:

復制代碼 代碼如下:

# -*- coding: utf-8 -*-
"""
A simple fibonacci program
"""
import argparse

parser = argparse.ArgumentParser(description='I print fibonacci sequence')
parser.add_argument('-s', '--start', type=int, dest='start',
                    help='Start of the sequence', required=True)
parser.add_argument('-e', '--end', type=int, dest='end',
                    help='End of the sequence', required=True)
parser.add_argument('-v', '--verbose', action='store_true', dest='verbose',
                    help='Enable debug info')

import logging

logger = logging.getLogger('fib')
logger.setLevel(logging.DEBUG)

hdr = logging.StreamHandler()
formatter = logging.Formatter('[%(asctime)s] %(name)s:%(levelname)s: %(message)s')
hdr.setFormatter(formatter)

logger.addHandler(hdr)


def infinite_fib():
    a, b = 0, 1
    yield a
    yield b
    while True:
        logger.debug('Before caculation: a, b = %s, %s' % (a, b))
        a, b = b, a + b
        logger.debug('After caculation: a, b = %s, %s' % (a, b))
        yield b


def fib(start, end):
    for cur in infinite_fib():
        logger.debug('cur: %s, start: %s, end: %s' % (cur, start, end))
        if cur > end:
            return
        if cur >= start:
            logger.debug('Returning result %s' % cur)
            yield cur

def main():
    args = parser.parse_args()
    if args.verbose:
        logger.setLevel(logging.DEBUG)
    else:
        logger.setLevel(logging.ERROR)

    for n in fib(args.start, args.end):
        print n,

if __name__ == '__main__':
    main()

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 连南| 宽甸| 闻喜县| 武强县| 揭阳市| 奇台县| 措美县| 乳山市| 虎林市| 布拖县| 平顺县| 崇义县| 临猗县| 平顺县| 呼伦贝尔市| 太湖县| 北碚区| 乐东| 济南市| 长岭县| 修文县| 永城市| 图片| 始兴县| 东乌| 苍梧县| 沁源县| 十堰市| 施秉县| 兴义市| 元朗区| 崇明县| 林州市| 桃江县| 武定县| 白河县| 阜南县| 贺州市| 道真| 桃园县| 和平区|