金庆的专栏

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  380 随笔 :: 0 文章 :: 454 评论 :: 0 Trackbacks
使用Python的logging.config

Python的logging模块接口仿log4j,概念上一致,使用上相当方便。
利用logging.config.fileConfig(),可以将日志的配置用文件来描述,简化了日志的初始化。

例程:
# test.py
import logging
import logging.config

logging.config.fileConfig(
"logging.conf")

#create logger
logger = logging.getLogger("example")

#"application" code
logger.debug("debug message")
logger.info(
"info message")
logger.warn(
"warn message")
logger.error(
"error message")
logger.critical(
"critical message")

logHello 
= logging.getLogger("hello")
logHello.info(
"Hello world!")



配置文件示例如下:
# logging.conf

[loggers]
keys
=root,example

[handlers]
keys
=consoleHandler,rotateFileHandler

[formatters]
keys
=simpleFormatter

[formatter_simpleFormatter]
format
=[%(asctime)s](%(levelname)s)%(name)s : %(message)s

[logger_root]
level
=DEBUG
handlers
=consoleHandler,rotateFileHandler

[logger_example]
level
=DEBUG
handlers
=consoleHandler,rotateFileHandler
qualname
=example
propagate
=0

[handler_consoleHandler]
class
=StreamHandler
level
=DEBUG
formatter
=simpleFormatter
args
=(sys.stdout,)

[handler_rotateFileHandler]
class
=handlers.RotatingFileHandler
level
=DEBUG
formatter
=simpleFormatter
args
=('test.log', 'a', 200000, 9)



注意,RotatingFileHandler中doRollover()会因为rename()出错而中途退出,造成日志文件没有打开,并且后继的日志消息都因为日志文件没有打开而失败。可以自己在rename()处加上try,或者不用RotatingFileHandler。估计隔一段时间就fileConfig()一次也是可以恢复正常。
详见:Python logging RotatingFileHandler bug

该错误仅当日志文件满时切换文件时才可能发生,当文件被锁定时才会出错。正常使用不会有问题,并且日志出错不会影响主程序的运行。所以可以放心使用,想再可靠点就直接在源码中加个try.

(转载请注明来源于金庆的专栏)


posted on 2007-09-03 11:35 金庆 阅读(5993) 评论(6)  编辑 收藏 引用 所属分类: 6. Python

评论

# 请教一下: 2007-10-30 10:19 APACHE
现在我有个问题想问一下,我打开一个LOG文件并输出,最后怎么关闭这个LOG文件呢?shutdown?
代码如下:
class CLogInfo:
#output the information to log,it will be instanced in testcase modele.
def __init__(self,logfile="testcase.log"):
try:
import logging
self.logger = None
self.logger = logging.getLogger()
self.hdlr = logging.FileHandler(logfile)
formatter = logging.Formatter("[%(asctime)s]: %(message)s","%Y-%m-%d %H:%M:%S")
self.hdlr.setFormatter(formatter)
self.logger.addHandler(self.hdlr)
self.logger.setLevel(logging.DEBUG)
except:
print "log init error!"
#exit(1)

def output(self,logInfo,errFlag=0):
try:
if (errFlag):
self.logger.error("error:"+logInfo)
#exit(errFlag)
else:
self.logger.info(logInfo)
except:
print "log output error!"
#exit(1)

def close(self):
try:
logging.shutdown([self.hdlr])
except error:
print "log closed error!"
#exit(1)

然后运行:
from logtest import CLogInfo,c1
log = CLogInfo("1.log")
log.output("aaa right")
这些都正确,但是
log.close()就提示错误,有知道如何关闭log文件的么?  回复  更多评论
  

# ok 2007-10-30 10:39 APACHE
I have find it:
self.logger.removeHandler(self.hdlr)  回复  更多评论
  

# re: 使用Python的logging.config 2007-10-30 11:07 金庆
@APACHE
我试了一下是好用的,没有错误,除了logging,error未定义。
你最好给出错误信息。
logging.shutdown()是关闭所有处理器。
用self.hdlr.close()也可以。  回复  更多评论
  

# re: 使用Python的logging.config 2008-07-25 17:03 feinix
我有个问题想问一下,我想用log直接写进数据库

看见网上的例子14
改为

# vim: set fileencoding=<encoding name> :
#!/usr/bin/env python
#coding=utf-8
#import tableE
from sqlobject import *
#from sqlobject import SQLObject
import sys, string, time, logging

connection=connectionForURI('sqlite:/d|/fff.db')
sqlhub.processConnection = connection


class DBHandler(logging.Handler):


def __init__(self, dsn, uid='', pwd=''):
logging.Handler.__init__(self)
#import mx.ODBC.Windows
class execptionsf(SQLObject):
Created= DateTimeCol
Name= StringCol()
LogLevel= StringCol()
LevelText= StringCol()
Message= StringCol()
Filename= StringCol()
Pathname= StringCol()
Lineno= StringCol()
Milliseconds= StringCol()
Exception= StringCol()
Thread= StringCol()
execptionsf.createTable(ifNotExists=True)




#def _set_Execptions(self,Created,RelativeCreated,Name,LogLevel,LevelText,Message,Filename,Pathname,Lineno,Milliseconds,Exception,Thread):


#self.dsn = dsn
#self.uid = uid
#self.pwd = pwd
#self.conn = mx.ODBC.Windows.connect(self.dsn, self.uid, self.pwd)
#self.SQL =
"""INSERT INTO Events (
Created,
RelativeCreated,
Name,
LogLevel,
LevelText,
Message,
Filename,
Pathname,
Lineno,
Milliseconds,
Exception,
Thread
)
VALUES (
%(dbtime)s,
%(relativeCreated)d,
'%(name)s',
%(levelno)d,
'%(levelname)s',
'%(message)s',
'%(filename)s',
'%(pathname)s',
%(lineno)d,
%(msecs)d,
'%(exc_text)s',
'%(thread)s'
);
"""
#self.cursor = self.conn.cursor()

def formatDBTime(self, record):
record.dbtime = time.strftime("#%m/%d/%Y#", time.localtime(record.created))

def emit(self, record):
try:
#use default formatting
self.format(record)
#now set the database time up
self.formatDBTime(record)
if record.exc_info:
record.exc_text = logging._defaultFormatter.formatException(record.exc_info)
else:
record.exc_text = ""

execptionsf.Created= %(dbtime)s
execptionsf.RelativeCreated=Created
execptionsf.Name= '%(name)s'
execptionsf.LogLevel= '%(levelno)s'
execptionsff.LevelText= '%(levelname)s'
execptionsf.Message= '%(message)s'
execptionsf.Filename= '%(filename)s'
execptionsf.Pathname= '%(pathname)s'
execptionsf.Lineno= '%(lineno)s'
execptionsf.Milliseconds= '%(msecs)s'
execptionsf.Exception= '%(exc_text)s'
execptionsf.Thread= '%(thread)s'

#sql = self.SQL % record.__dict__
#self.cursor.execute(sql)
#self.conn.commit()
except:
import traceback
ei = sys.exc_info() #get the tracebak infomation
traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
del ei

def close(self):
#self.cursor.close()
#self.conn.close()
logging.Handler.close(self)

dh = DBHandler('Logging')
logger = logging.getLogger("")
# logger
# logger.setLevel(logging.DEBUG)
logger.addHandler(dh)
logger.debug('debug')
logger.info('info')
logger.warning('warning')
logger.error('error')
logger.critical('critical')

try:
import math
math.exp(1000)
except:
logger.exception("Problem with %s", "math.exp")
logging.shutdown()

不知道怎么错误了……因为我不知道,Log的信息什么的由哪里传递出来。  回复  更多评论
  

# re: 使用Python的logging.config 2008-07-25 18:26 金庆
@feinix
错误信息呢?还要给出原例子的地址,看看你改了什么?
  回复  更多评论
  

# re: 使用Python的logging.config 2008-07-26 16:22 feinix
@金庆
多谢,我已经找到了,是那个record,它带有相关的属性值。

我想知道,这里边的config和log程序的编写,有什么关系么?可以用设置来代替编写?而且你写这个日志程序怎么使用?在每个需要的模块中直接调用?  回复  更多评论
  


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理