【问题标题】:How to handle global logging in Python when (some) classes need to be pickled当(某些)类需要腌制时如何在 Python 中处理全局日志记录
【发布时间】:2015-01-24 17:59:09
【问题描述】:

我有一个关于登录 Python 的问题。情况如下:我的应用程序有一个全局上下文对象(单例),其中包括一个记录器对象。所有需要使用日志记录的类都可以从上下文中获取这个全局记录器对象,并使用它来输出消息。

但是,一些包含此类记录器的对象需要保存到 pickle 文件中。当腌制对象具有对打开的 FileHandler 的引用时,保存到腌制不起作用,在这种情况下,对象就是这种情况,因为它们拥有记录器,因此是打开的文件处理程序。

现在,我可以在酸洗之前删除所有文件处理程序,如下所示:

def closeLogFile(self):
    handlers = self.logger.handlers[:]
    for handler in handlers:
        handler.close()
        self.logger.removeHandler(handler)

但这有一个副作用,即对于仍然持有对全局记录器的引用的所有其他对象,日志处理程序也会被删除。

有什么更好的方法既允许全局记录到同一个文件又允许酸洗单个类?

提前一百万谢谢。

干杯,

马丁

【问题讨论】:

    标签: python logging pickle


    【解决方案1】:

    如果您使用dill 而不是pickle,它可能对您有用。 dill 可以处理对FileHandles 的引用,并具有适应不同用例的变体。这是默认值:

    >>> import dill
    >>> import logging
    >>> l = logging.Logger('foo')
    >>>
    >>> class Foo(object):
    ...   def __init__(self, x):
    ...     self.logger = l
    ...     self.x = x
    ...     self.other = logging.Logger('bar')
    ... 
    >>> f = Foo(4)
    >>> f.logger
    <logging.Logger object at 0x1094d3210>
    >>> f.other
    <logging.Logger object at 0x1094d34d0>
    >>>
    >>> f_ = dill.dumps(f)
    >>> _f = dill.loads(f_)
    >>> 
    >>> _f.logger
    <logging.Logger object at 0x1094f1c90>
    >>> _f.other
    <logging.Logger object at 0x1094f1b50>
    

    请注意,未选择的Logger 实例与原始实例不同,但它们仍指向相同的日志。您实际上得到了一个新类__main__.Foo,因为默认情况下dill 腌制类对象而不是腌制引用。这种行为应该扩展到不同的类——基本上旧的__main__.Foo 和新的__main__.Foo 已经证明了这一点。

    【讨论】:

    • 非常感谢,迈克。这完美地工作。我会用莳萝代替泡菜。只是为了回答:为了保存到特定的文件路径,应该使用以下语法: with open(path, "wb") as f: dill.dump(clf, f)
    • 酷。是的,dilldumpdumps 使用与pickle 相同的语法,尽管dill 有一些额外的选项用于特殊处理文件和类。
    猜你喜欢
    • 2011-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-30
    • 2019-06-08
    相关资源
    最近更新 更多