我有一些记录器用于多个程序,每个程序都在一个"__main__"记录器中配置了多个处理程序,另一个包创建了一个"__main__.package"记录器,所以它使用该配置来处理它的消息.我没有控制程序的记录器,只有我的包.我的包应该使用记录器设置.我可以假设每个使用我包的程序都配置了一个.

我想从main继承格式化程序,但在将消息/格式发送到格式化程序之前修改它.一些非常类似的this问题,除了我正在与一个子元素日志(log)记录器而不是家长日志(log)直接工作.

例如:

main.py

import logging
import mypackage
logger = logging.getLogger("__main__")
logger.setLevel(logging.DEBUG)
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)
stream_formatter = logging.Formatter('%(levelname)s:%(filename)s:%(lineno)d:%(message)s')
stream_handler.setFormatter(stream_formatter)
logger.addHandler(stream_handler)    

def main():
    a=1
    logger.info("message from main")
    b = mypackage.MyClass("EXTRA INSTANCE INFO")
    b.mymodule(a)

    c = mypackage.MyClass("EXTRA INSTANCE INFO2")
    c.mymodule(a+1)
    
main()

我try 添加此信息是为了修改邮件,方法是添加在邮件输出之前修改邮件的筛选器:

mypackage.py

import logging
logger = logging.getLogger(f"__main__.{__name__}")

class _PackageContextFilter(logging.Filter):

    def __init__(self, needed_info_from_my_package):
        self.needed_info_from_my_package=needed_info_from_my_package

    def filter(self, record):
        record.msg = f"({self.needed_info_from_my_package}) " + record.msg
        return True
    
class MyClass():
    def __init__(self,init_cond) -> None:
        self.data=[]
        self.needed_info_from_my_package = [init_cond]
        # I think the issue arises here because a single logger object gets multiple filters
        logger.addFilter(_PackageContextFilter(self.needed_info_from_my_package))
        
        
    def mymodule(self,data):
        self.data.append(data)
        logger.info(f"message from mymodule about {self.data}")
       

输出:

INFO:main.py:13:message from main
INFO:mypackage.py:24:(['EXTRA INSTANCE INFO']) message from mymodule about [1]
INFO:mypackage.py:24:(['EXTRA INSTANCE INFO2']) (['EXTRA INSTANCE INFO']) message from mymodule about [2]

我想要的输出是

INFO:main.py:13:message from main
INFO:mypackage.py:24:(['EXTRA INSTANCE INFO']) message from mymodule about [1]
INFO:mypackage.py:24:(['EXTRA INSTANCE INFO2']) message from mymodule about [2]

我认为这是重复的,因为我一直在向同一个日志(log)对象添加过滤器.我看到在logging cookbook中有一个创建上下文变量来处理某个类的两个实例的示例,但当我查找有关上下文变量是什么的文档时,它似乎与线程更相关.我不确定创建它们来解决这个问题是不是一个"好主意".

我想我可以做的另一种 Select 是将每一个输入包装到日志(log)消息中,如logging.info(self.format_message_instance(msg)),但我认为有一个已知的最佳实践

推荐答案

正常情况下,筛选器不会引用调用它的MyClass实例,因此它不知道要向消息添加什么信息.使用与cookbook示例类似的每个实例唯一的适配器如何:

class CustomAdapter(logging.LoggerAdapter):
    def process(self, msg, kwargs):
        return f"({self.extra['info']}) {msg}", kwargs

    
class MyClass():
    def __init__(self,init_cond) -> None:
        self.data=[]
        self.needed_info_from_my_package = [init_cond]
        # here we initialize based on the main logger
        self.logger = CustomAdapter(logger, {'info': self.needed_info_from_my_package})
        
        
    def mymodule(self,data):
        self.data.append(data)
        self.logger.info(f"message from mymodule about {self.data}")

Python相关问答推荐

具有多个选项的计数_匹配

Python多处理:当我在一个巨大的pandas数据框架上启动许多进程时,程序就会陷入困境

Polars LazyFrame在收集后未返回指定的模式顺序

难以在Manim中正确定位对象

删除所有列值,但判断是否存在任何二元组

如何从pandas的rame类继承并使用filepath实例化

在极性中创建条件累积和

利用Selenium和Beautiful Soup实现Web抓取JavaScript表

在含噪声的3D点网格中识别4连通点模式

无论输入分辨率如何,稳定扩散管道始终输出512 * 512张图像

AES—256—CBC加密在Python和PHP中返回不同的结果,HELPPP

如何排除prefecture_related中查询集为空的实例?

Discord.py -

BeautifulSoup-Screper有时运行得很好,很健壮--但有时它失败了::可能这里需要一些更多的异常处理?

如何在Python中将超链接添加到PDF中每个页面的顶部?

你能把函数的返回类型用作其他地方的类型吗?'

高效生成累积式三角矩阵

在round函数中使用列值

如何在Quarto中的标题页之前创建序言页

保存由PYTHON在EXCEL中所做更改的问题