如何腌制伐木机?

发布于 2024-09-11 20:33:02 字数 528 浏览 5 评论 0原文

所从事的项目要求我能够在任何时候对容器对象进行 pickle,因为我们希望它在外部条件下经常失败,并且能够完全从我们中断的地方继续。

我非常广泛地使用 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 上重新创建它。

Working on a project that requires that I am able to pickle the container object at any point, since we expect it to fail on external conditions quite frequently and be able to fully pick up where we left off.

I'm using the python logging library quite extensively, and all of my classes start by setting up a logger like:

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

Since I'm pickling a container class, it has several layers of classes within it, each with their own logger instance.

Now, for some reason, these loggers are breaking Pickle. I'm getting the following error, which goes away if I delete self.logger from all the classes:

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

So my question is whether or not there is some way to remove the lock objects from all the loggers without having to recurse through my whole object tree deleting loggers which I will have to recreate on unpickle.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

本宫微胖 2024-09-18 20:33:02

您还可以创建一个类来实现返回所需记录器的属性。从这个“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")

You could also create a class that implements a property which returns the needed logger. Every class which inherits from this "LoggerMixin" is now able to use the logger in the same way you were using it before.

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")
那小子欠揍 2024-09-18 20:33:02

Python 3.7 中的新增功能 (bpo30520)

Logger 现在可以像许多其他对象一样进行 pickle 。

import pickle
import logging
log = logging.getLogger(__name__)
logger_pickle = pickle.dumps(log)

# and of coarse, to load:
log = pickle.loads(logger_pickle)

New in Python 3.7 (bpo30520)

Logger can now be pickled like many other objects.

import pickle
import logging
log = logging.getLogger(__name__)
logger_pickle = pickle.dumps(log)

# and of coarse, to load:
log = pickle.loads(logger_pickle)
永不分离 2024-09-18 20:33:02

您可以创建一个包装记录器并实现 __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

You could create a class that wraps the logger and implements __getstate__ and
__setstate__.

This is pasted from http://docs.python.org/library/pickle.html. The fh is handled in a way which may be similar to what you need.

#!/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
甜扑 2024-09-18 20:33:02

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

如何阻止属性在Python中被腌制

编辑:使用这个答案:如何在Python中阻止属性被pickle

Found a very similar question here, with an answer that worked for me:

How to stop attributes from being pickled in Python

edit: used this answer: How to stop attributes from being pickled in Python

梦毁影碎の 2024-09-18 20:33:02

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

>>> 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>

You could have used dill here, which can pickle loggers and locks.

>>> 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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文