临时更改Python日志处理器
我正在开发一个应用程序,使用标准的日志模块来记录日志。我们的设置是根据不同的级别等,将日志记录到多个文件中。同时,我们还使用celery来处理一些主应用程序之外的任务(通常是一些耗时的维护工作)。
这个celery任务除了调用一些函数(比如说spam
)来完成实际工作外,什么也不做。这些函数使用日志模块来输出状态信息。现在,我想写一个装饰器,能够拦截所有spam
函数的日志调用,并将它们放入一个StringIO
中,这样我就可以把它们放到其他地方。
我想到的一个解决方案是在函数执行期间,为根日志记录器插入一个处理器,以捕获所有日志信息。不过,这样做会干扰全局共享对象,可能会在后面造成问题。
我看到过这个回答,但它并不是我想要的解决方案。
2 个回答
0
对于StringIO处理器,你可以为根日志记录器添加一个额外的处理器,这样可以捕捉到所有的日志信息,但同时加一个虚假的过滤器(Logger.addFilter),这个过滤器会把所有的日志信息都过滤掉(所以实际上什么都不会被记录到StringIO中)。
然后,你可以为spam函数写一个装饰器,在函数执行之前移除这个过滤器(Logger.removeFilter),执行完后再把虚假的过滤器加回来。
2
关于StringIO的事情是,可能会有多个进程在运行(比如Celery任务),所以会有多个StringIO,对吧?
你可以这样做:
- 在Celery运行的进程中,给根日志记录器添加一个处理器,这个处理器可以把事件发送到一个套接字(如果是TCP就用SocketHandler,如果是UDP就用DatagramHandler)。
- 创建一个套接字接收器来接收和处理这些事件,具体的做法可以参考这里。这样就可以在多个Celery进程之间整合成一个统一的StringIO。
如果你在使用多进程,也可以参考这里描述的方法。虽然那篇文章是关于Python 3.2的,但Python 2.x也可以用logutils实现类似的功能。
更新:如果你想避免使用单独的接收进程,可以直接把日志记录到数据库,使用类似于这个答案中的处理器。如果你想在进程结束之前都不记录日志,可以使用MemoryHandler
和数据库处理器结合来实现。