在Python中使用多重处理时应如何记录?

发布于 2021-02-02 23:12:27

现在,我在框架中有一个中央模块,该模块使用Python 2.6 multiprocessing模块产生多个进程。由于使用multiprocessing,因此存在模块级的多处理感知日志LOG = multiprocessing.get_logger()。根据文档,此记录器具有进程共享的锁,因此你不会sys.stderr通过同时写入多个进程来乱码内容(或任何文件句柄)。

我现在遇到的问题是框架中的其他模块不支持多处理。以我的方式看,我需要使这个中央模块上的所有依赖项都使用支持多处理的日志记录。在框架内这很烦人,更不用说框架的所有客户了。有我没有想到的替代方法吗?

关注者
0
被浏览
71
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    现在,它使用队列来正确处理并发,并且还可以从错误中正确恢复。我现在已经在生产中使用它几个月了,下面的当前版本可以正常工作。

    from logging.handlers import RotatingFileHandler
    import multiprocessing, threading, logging, sys, traceback
    
    class MultiProcessingLog(logging.Handler):
        def __init__(self, name, mode, maxsize, rotate):
            logging.Handler.__init__(self)
    
            self._handler = RotatingFileHandler(name, mode, maxsize, rotate)
            self.queue = multiprocessing.Queue(-1)
    
            t = threading.Thread(target=self.receive)
            t.daemon = True
            t.start()
    
        def setFormatter(self, fmt):
            logging.Handler.setFormatter(self, fmt)
            self._handler.setFormatter(fmt)
    
        def receive(self):
            while True:
                try:
                    record = self.queue.get()
                    self._handler.emit(record)
                except (KeyboardInterrupt, SystemExit):
                    raise
                except EOFError:
                    break
                except:
                    traceback.print_exc(file=sys.stderr)
    
        def send(self, s):
            self.queue.put_nowait(s)
    
        def _format_record(self, record):
            # ensure that exc_info and args
            # have been stringified.  Removes any chance of
            # unpickleable things inside and possibly reduces
            # message size sent over the pipe
            if record.args:
                record.msg = record.msg % record.args
                record.args = None
            if record.exc_info:
                dummy = self.format(record)
                record.exc_info = None
    
            return record
    
        def emit(self, record):
            try:
                s = self._format_record(record)
                self.send(s)
            except (KeyboardInterrupt, SystemExit):
                raise
            except:
                self.handleError(record)
    
        def close(self):
            self._handler.close()
            logging.Handler.close(self)
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看