Python 将来自两个模块的消息记录到不同的文件中,并包括来自使用其他日志记录工具的模块的日志记录

Python 将来自两个模块的消息记录到不同的文件中,并包括来自使用其他日志记录工具的模块的日志记录,python,logging,Python,Logging,我有一个导入两个模块的脚本-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和clien

我有一个导入两个模块的脚本-
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
使用不同的参数调用函数,但它们最终会覆盖彼此的设置(因此最后一次调用获胜)

很明显,我可以使用多个记录器。阻止我这样做的是

  • 各种下游脚本/模块使用一些其他日志记录工具(例如Twisted和
    smtplib
    的内部工具)
  • 某些设施只能使用“默认”目的地
所以我想这些日志条目将会丢失,除非我创建一组广泛的覆盖代码


问题是:为
mailserver.py
client.py
及其所有相关模块设置两个日志目的地的最佳做法是什么?

不要使事情过于复杂。尽可能使用单个日志记录设施

健全的日志记录设施(包括
日志记录
)不要求每个模块指定日志位置,仅需要在某个专用位置(例如,在主模块中)指定日志位置

所以用一个。对于导入模块中的
日志记录
,这与

l=logging.getLogger('<distinguishing name>')
#use l's methods
这样,我就有了一个日志文件,其中包含来自我的程序的消息,
smtplib
smtpd
asyncore
,并适当地标记了(
%(名称)s
字段)

使用
Logging

创建多个
处理程序
s,并将
过滤器
s附加到只需要包含特定消息的人。要按源库进行区分,您可能会按
名称

进行筛选,谢谢,但这并不能向我解释(至少我不这么认为)如何将所有服务器日志消息(包括服务器脚本使用的库)和所有客户端日志消息(包括客户端脚本使用的库)都放到一个位置去另一个地方。此外,我们可能需要在每个服务器和客户机代码中包含日志设施定义,因为我们可能希望启动一个而不启动另一个……您没有指定哪个模块使用哪个设施,所以我不能说得更具体。我只能举一个我过去是怎么做的例子。啊,好的,谢谢@ivan_pozdeev-我想我明白了!我要试一试!:)重写以使其易于理解
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>