翻译实用的Python编程0802

北京看皮肤科好医院 http://m.39.net/pf/a_4781492.html
8.2日志

本节对日志模块(loggingmodule)进行简单的介绍。

logging模块

logging模块是用于记录诊断信息的Python标准库模块。日志模块非常庞大,具有许多复杂的功能。我们将会展示一个简单的例子来说明其用处。

再探异常

在本节练习中,我们创建这样一个parse()函数:

#fileparse.pydefparse(f,types=None,names=None,delimiter=None):records=[]forlineinf:line=line.strip()ifnotline:continuetry:records.append(split(line,types,names,delimiter))exceptValueErrorase:print("Couldntparse:",line)print("Reason:",e)returnrecords

请看到try-except语句,在except块中,我们应该做什么?

应该打印警告消息(warningmessage)?

try:records.append(split(line,types,names,delimiter))exceptValueErrorase:print("Couldntparse:",line)print("Reason:",e)

还是默默忽略警告消息?

try:records.append(split(line,types,names,delimiter))exceptValueErrorase:pass

任何一种方式都无法令人满意,通常情况下,两种方式我们都需要(用户可选)。

使用logging

logging模块可以解决这个问题:

#fileparse.pyimportlogginglog=logging.getLogger(__name__)defparse(f,types=None,names=None,delimiter=None):...try:records.append(split(line,types,names,delimiter))exceptValueErrorase:log.warning("Couldntparse:%s",line)log.debug("Reason:%s",e)

修改代码以使程序能够遇到问题的时候发出警告消息,或者特殊的Logger对象。Logger对象使用logging.getLogger(__name__)创建。

日志基础

创建一个记录器对象(loggerobject)。

log=logging.getLogger(name)#nameisastring

发出日志消息:

log.critical(message[,args])log.error(message[,args])log.warning(message[,args])log.info(message[,args])log.debug(message[,args])

不同方法代表不同级别的严重性。

所有的方法都创建格式化的日志消息。args和%运算符一起使用以创建消息。

logmsg=message%args#Writtentothelog日志配置

配置:

#main.py...if__name__==__main__:importlogginglogging.basicConfig(filename=app.log,#Logoutputfilelevel=logging.INFO,#Outputlevel)

通常,在程序启动时,日志配置是一次性的(译注:程序启动后无法重新配置)。该配置与日志调用是分开的。

说明

日志是可以任意配置的。你可以对日志配置的任何一方面进行调整:如输出文件,级别,消息格式等等,不必担心对使用日志模块的代码造成影响。

练习练习8.2:将日志添加到模块中

在fileparse.py中,有一些与异常有关的错误处理,这些异常是由错误输入引起的。如下所示:

#fileparse.pyimportcsvdefparse_csv(lines,select=None,types=None,has_headers=True,delimiter=,,silence_errors=False):ParseaCSVfileintoalistofrecordswithtypeconversion.ifselectandnothas_headers:raiseRuntimeError(selectrequirescolumnheaders)rows=csv.reader(lines,delimiter=delimiter)#Readthefileheaders(ifany)headers=next(rows)ifhas_headerselse[]#Ifspecificcolumnshavebeenselected,makeindicesforfilteringandsetoutputcolumnsifselect:indices=[headers.index(colname)forcolnameinselect]headers=selectrecords=[]forrowno,rowinenumerate(rows,1):ifnotrow:#Skiprowswithnodatacontinue#Ifspecificcolumnindicesareselected,pickthemoutifselect:row=[row[index]forindexinindices]#Applytypeconversiontotherowiftypes:try:row=[func(val)forfunc,valinzip(types,row)]exceptValueErrorase:ifnotsilence_errors:print(f"Row{rowno}:Couldntconvert{row}")print(f"Row{rowno}:Reason{e}")continue#Makeadictionaryoratupleifheaders:record=dict(zip(headers,row))else:record=tuple(row)records.append(record)returnrecords

请注意发出诊断消息的print语句。使用日志操作来替换这些print语句相对来说更简单。请像下面这样修改代码:

#fileparse.pyimportcsvimportlogginglog=logging.getLogger(__name__)defparse_csv(lines,select=None,types=None,has_headers=True,delimiter=,,silence_errors=False):ParseaCSVfileintoalistofrecordswithtypeconversion.ifselectandnothas_headers:raiseRuntimeError(selectrequirescolumnheaders)rows=csv.reader(lines,delimiter=delimiter)#Readthefileheaders(ifany)headers=next(rows)ifhas_headerselse[]#Ifspecificcolumnshavebeenselected,makeindicesforfilteringandsetoutputcolumnsifselect:indices=[headers.index(colname)forcolnameinselect]headers=selectrecords=[]forrowno,rowinenumerate(rows,1):ifnotrow:#Skiprowswithnodatacontinue#Ifspecificcolumnindicesareselected,pickthemoutifselect:row=[row[index]forindexinindices]#Applytypeconversiontotherowiftypes:try:row=[func(val)forfunc,valinzip(types,row)]exceptValueErrorase:ifnotsilence_errors:log.warning("Row%d:Couldntconvert%s",rowno,row)log.debug("Row%d:Reason%s",rowno,e)continue#Makeadictionaryoratupleifheaders:record=dict(zip(headers,row))else:record=tuple(row)records.append(record)returnrecords

完成修改后,尝试在错误的数据上使用这些代码:

importreporta=report.read_portfolio(Data/missing.csv)Row4:Badrow:[MSFT,,51.23]Row7:Badrow:[IBM,,70.44]

如果你什么都不做,则只会获得WARNING级别以上的日志消息。输出看起来像简单的打印语句。但是,如果你配置了日志模块,你将会获得有关日志级别,模块等其它信息。请按以下步骤操作查看:

importlogginglogging.basicConfig()a=report.read_portfolio(Data/missing.csv)WARNING:fileparse:Row4:Badrow:[MSFT,,51.23]WARNING:fileparse:Row7:Badrow:[IBM,,70.44]

你会发现,看不到来自于log.debug()操作的输出。请按以下步骤修改日志级别(译注:因为日志配置是一次性的,所以该操作需要重启命令行窗口):

logging.getLogger(fileparse).level=logging.DEBUGa=report.read_portfolio(Data/missing.csv)WARNING:fileparse:Row4:Badrow:[MSFT,,51.23]DEBUG:fileparse:Row4:Reason:invalidliteralforint()withbase10:WARNING:fileparse:Row7:Badrow:[IBM,,70.44]DEBUG:fileparse:Row7:Reason:invalidliteralforint()withbase10:

只留下critical级别的日志消息,关闭其它级别的日志消息。

logging.getLogger(fileparse).level=logging.CRITICALa=report.read_portfolio(Data/missing.csv)练习8.3:向程序添加日志

要添加日志到应用中,你需要某种机制来实现在主模块中初始化日志。其中一种方式使用看起来像下面这样的代码:

#Thisfilesetsupbasicconfigurationoftheloggingmodule.#Changesettingsheretoadjustloggingoutputasneeded.importlogginglogging.basicConfig(filename=app.log,#Nameofthelogfile(omittousestderr)filemode=w,#Filemode(useatoappend)level=logging.WARNING,#Logginglevel(DEBUG,INFO,WARNING,ERROR,orCRITICAL))

再次说明,你需要将日志配置代码放到程序启动步骤中。例如,将其放到report.py程序里的什么位置?

注:完整翻译见



转载请注明地址:http://www.sanbaicaoasb.com/scgj/8135.html
  • 上一篇文章:
  • 下一篇文章:
  • 热点文章

    • 没有热点文章

    推荐文章

    • 没有推荐文章