如何腌制伐木工人?

Jos*_*erg 7 python logging pickle

处理一个项目,要求我能够在任何时候挑选容器对象,因为我们期望它在外部条件下经常失败,并且能够完全从我们中断的地方开始.

我正在广泛使用python日志库,我的所有类都开始设置一个记录器,如:

class foo:
   def __init__(self):
       self.logger = logging.getLogger("package.foo")
Run Code Online (Sandbox Code Playgroud)

由于我正在挑选一个容器类,它里面有几层类,每个类都有自己的记录器实例.

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

Can't pickle 'lock' object: <thread.lock object at ... >
Run Code Online (Sandbox Code Playgroud)

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

小智 11

您还可以创建一个实现返回所需记录器的属性的类.从"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")
Run Code Online (Sandbox Code Playgroud)


abc*_*ccd 7

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)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,Loggers 可以被 pickle;然而,它所做的只是再次调用 getLogger。因此,如果您使用多进程,则仍然需要在使用生成的进程记录器之前配置日志记录。 (6认同)

Jam*_*oth 5

您可以创建一个包装记录器并实现__getstate__and 的类 __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
Run Code Online (Sandbox Code Playgroud)


Jos*_*erg 2

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

如何在 Python 中阻止属性被 pickle

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