【问题标题】:How to pickle loggers?如何腌制伐木工?
【发布时间】:2010-07-30 21:22:08
【问题描述】:

从事一个需要我能够随时腌制容器对象的项目,因为我们预计它会经常在外部条件下失败,并且能够从我们中断的地方完全恢复。

我非常广泛地使用 python 日志库,我的所有课程都从设置一个记录器开始,如下所示:

class foo:
   def __init__(self):
       self.logger = logging.getLogger("package.foo")

因为我正在挑选一个容器类,它里面有好几层类,每一层都有自己的记录器实例。

现在,出于某种原因,这些记录器正在破坏 Pickle。我收到以下错误,如果我从所有类中删除 self.logger,该错误就会消失:

Can't pickle 'lock' object: <thread.lock object at ... >

所以我的问题是,是否有某种方法可以从所有记录器中删除锁定对象,而不必通过我的整个对象树递归删除记录器,我必须在 unpickle 上重新创建。

【问题讨论】:

    标签: python logging pickle


    【解决方案1】:

    您还可以创建一个实现返回所需记录器的属性的类。从这个“LoggerMixin”继承的每个类现在都可以像以前一样使用记录器了。

    class LoggerMixin():
        @property
        def logger(self):
            component = "{}.{}".format(type(self).__module__, type(self).__name__)
            return logging.getLogger(component)
    
    class Foo(LoggerMixin):
        def __init__(self):
            self.logger.info("initialize class")
    
        def bar(self):
            self.logger.info("execute bar")
    

    【讨论】:

    • 这是一个被忽视但很好的回应。
    【解决方案2】:

    您可以创建一个类来包装记录器并实现__getstate____setstate__.

    这是从http://docs.python.org/library/pickle.html 粘贴的。 fh 的处理方式可能与您需要的类似。

    #!/usr/local/bin/python
    
    class TextReader:
        """Print and number lines in a text file."""
        def __init__(self, file):
            self.file = file
            self.fh = open(file)
            self.lineno = 0
    
        def readline(self):
            self.lineno = self.lineno + 1
            line = self.fh.readline()
            if not line:
                return None
            if line.endswith("\n"):
                line = line[:-1]
            return "%d: %s" % (self.lineno, line)
    
        def __getstate__(self):
            odict = self.__dict__.copy() # copy the dict since we change it
            del odict['fh']              # remove filehandle entry
            return odict
    
        def __setstate__(self, dict):
            fh = open(dict['file'])      # reopen file
            count = dict['lineno']       # read from file...
            while count:                 # until line count is restored
                fh.readline()
                count = count - 1
            self.__dict__.update(dict)   # update attributes
            self.fh = fh                 # save the file object
    

    【讨论】:

      【解决方案3】:

      Python 3.7 中的新功能 (bpo30520)

      Logger 现在可以像许多其他对象一样被腌制。

      import pickle
      import logging
      log = logging.getLogger(__name__)
      logger_pickle = pickle.dumps(log)
      
      # and of coarse, to load:
      log = pickle.loads(logger_pickle)
      

      【讨论】:

      • 请注意,Loggers 可以腌制;但是,它所做的只是再次调用 getLogger。因此,如果您使用多进程,您仍然需要在使用派生的 Processes Logger 之前配置 Logging。
      【解决方案4】:

      在这里找到了一个非常相似的问题,答案对我有用:

      How to stop attributes from being pickled in Python

      编辑:使用这个答案:How to stop attributes from being pickled in Python

      【讨论】:

      • 也许您可以链接到(或引用)您使用的确切答案? (有两个)在任何答案下方都有一个“链接”按钮,您可以点击该网址。
      【解决方案5】:

      您可以在这里使用dill,它可以腌制记录器和锁。

      >>> class foo:
      ...    def __init__(self):
      ...        self.logger = logging.getLogger("package.foo")
      ... 
      >>> import dill
      >>> import logging
      >>> 
      >>> f = foo()
      >>> _f = dill.dumps(f)  
      >>> f_ = dill.loads(_f)
      >>> f_.logger
      <logging.Logger object at 0x110b1d250>
      

      【讨论】:

        猜你喜欢
        • 2014-10-13
        • 1970-01-01
        • 2012-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多