好吧,在玩了一些之后,这是我想出的解决方案:
def log_iterator(logger_names):
'''
Get an iterator that returns LogRecord objects whenever a log message is made.
logger_names can be:
a string identifying which logger you want to get messages iterate from
a list identifying all the loggers you want to get messages from
a dict<name: level> where level identifies the minimum loggling level
you want (default is INFO)
'''
if isinstance(logger_names, str):
logger_names = {logger_names: logging.INFO}
elif isinstance(logger_names, (list, tuple)):
logger_names = {name: logging.INFO for name in logger_names}
log_message_event = threading.Event()
;你应该使用 items() 因为 iteritems() 已被弃用
for logger_name, log_level in logger_names.iteritems():
logger = logging.getLogger(logger_name)
logger.addHandler(FireOnLog(log_message_event, log_level))
while True:
log_message_event.wait()
record = log_message_event.record
log_message_event.clear()
yield record
class FireOnLog(logging.StreamHandler):
'''
Custom loghandler that fires an event every time a log message
comes in. To use, you need to add this handler to a logger.
'''
def __init__(self, event, log_level = logging.INFO):
'''
Event is a threading.Event object
log_level is the minimum logging level you want
'''
logging.StreamHandler.__init__(self)
self._event = event
self._log_level = log_level
def emit(self, record):
if record.levelno >= self._log_level:
self._event.record = record
self._event.set()
使用以下代码测试时表现正确:
def _print_messages():
print 'Started Printing loop'
for log_record in log_iterator(['testlog', 'anotherlog']):
print '%s:%s:%s' % (log_record.levelname, log_record.name, log_record.message)
def test_log_handling():
t = threading.Thread(target = _print_messages)
t.start()
time.sleep(.1)
logging.getLogger('testlog').critical('Message!')
logging.getLogger('anotherlog').critical('Another Message right away')
logging.getLogger('badlog').critical("Someething useless that you don't want to hear")
time.sleep(.1)
logging.getLogger('testlog').critical('Another Message after some wait')
这似乎是 python 内置的非常通用的功能,所以如果有人知道如何使用内置函数执行此操作,请回复,我会给你一个点!