我有一个导入两个模块的脚本 - mailserver.py
和client.py
。其中每个都有一个方法,类似于:
def startLogger(logPath):
log.discardLogs()
d = os.path.dirname(logPath)
if not os.path.exists(d):
os.makedirs(d)
log.startLogging(open(logPath, 'a'))
然后我使用与mailserver.py
和client.py
不同的参数调用该函数,但它们最终会覆盖彼此的设置(因此最后一次调用获胜)。
显然,我可以根据Logging Cookbook使用多个记录器。是什么阻止了我
smtplib
的内部工具)所以我猜这些日志条目会丢失,除非我创建了一组广泛的重写代码。
问题是:为mailserver.py
和client.py
及其所有相关模块设置两个日志记录目标的最佳做法是什么?
答案 0 :(得分:1)
不要过度复杂化。尽可能使用单一的日志工具。
一个理智的日志记录工具(包括logging
)不要求每个模块指定日志位置等 - 它们只需要在某个专用位置指定(例如在主模块中)。
所以使用一个。对于logging
,在导入的模块中,这就像
l=logging.getLogger('<distinguishing name>')
#use l's methods
如果您想同时使用logging
和twisted
进行登录,最好写一个logging
Handler
,将邮件复制到Twisted。
在我之前的一个项目(使用smtplib
和smtpd
的SMTP代理)中,这是
我如何在logging
:
import logging
l = logging.getLogger() #root logger to be used in the main module
f = logging.Formatter('%(asctime)s %(process)d:%(thread)d %(name)s %(levelname)-8s %(message)s')
<set log file, install an excepthook to log unhandled exceptions>
class LogStream(smtpd.Devnull):
"""A write-only stream-like interface to logging module.
write() and flush() are the public interface"""
def __init__(self,name=None,level=logging.DEBUG):
def write(self,s):
"""log the data, line-buffered; uses flush() with argument internally"""
def flush(self,p=None):
"""log and remove `p' (default - all) bytes from the buffer.
The `p' parameter is not a part of the public interface"""
class asyncore_logger:
<some settings>
@classmethod
def log(cls,msg,level='info'):
"""A compatible replacement for asyncore.dispatcher.log_info.
The class is only needed as a settings container"""
smtpd.DEBUGSTREAM=LogStream('smtpd')
#smtpd logs receipts but not replies
smtpd.SMTPChannel.push=<custom_wrapper_using_DEBUGSTREAM>(smtpd.SMTPChannel.push)
smtplib.stderr=LogStream('smtplib')
asyncore.dispatcher.log_info = asyncore_logger.log
#clean up entries that are no longer needed in the local namespace
del LogStream, asyncore_logger, <custom_wrapper_using_DEBUGSTREAM>
有了这个,我有一个日志文件,其中包含来自我的程序smtplib
,smtpd
和asyncore
的消息,这些消息已正确标记(%(name)s
字段)。
logging
创建多个Handler
并将Filter
附加到需要仅包含特定邮件的用户。要通过源库区分,您可能会按name
进行过滤。