python - 如何重构返回闭包的方法以使其可 pickle ?

标签 python pickle

我的具体问题与 Django 相关,但我将相关代码重写为通用 Python 以便更好地理解。

import pickle


class FieldTracker(object):
    def patch_save(self, instance):
        original_save = instance.save

        def save(**kwargs):
            ret = original_save(**kwargs)

            # use properties of self, implement new stuff etc
            print 'Used patched save'

            return ret

        instance.save = save


class Model(object):
    name_field = 'joe'

    field_tracker = FieldTracker()

    def __init__(self):
        self.field_tracker.patch_save(self)

    def save(self):
        print 'Used default save'

model = Model()
model.save()  # Uses patched version of save

pickle.dumps(model)  # Fails

Model 是数据库行的表示。 FieldTracker 跟踪 Model 中字段的更改(在本例中为 name_field)。 FieldTracker 需要在实例化 Model 后修补 save 方法。修补的 savepatch_save 内部的闭包,因为它使用 FieldTracker 中的属性,从传递的 instance 等调用方法。

如果

FieldTracker 的方法包含闭包,则无法将其作为一个 pickle。根据我的尝试,save 无法移动到类级别,因为我收到 TypeError: can't pickle instancemethod objects。当我尝试将 patch_save 移至顶层时,它产生了与上面代码相​​同的异常(惊讶,惊讶)。将 save 移动到顶层可能意味着使用全局变量,我想避免这种情况(但我实际上还没有尝试过)。

问题是:是否可以将 FieldTracker 代码重构为可pickle,或者我应该使用不同的方法(例如将覆盖的 save 移动到模型 mixin)?

This如果有人关心的话,它是真正的FieldTracker

最佳答案

为什么要费力重构?我猜您真的对在编写类和实例时对其进行 pickle 感兴趣,对吧?为此,我将使用 dill ,它几乎可以 pickle python 中的任何东西。

>>> import dill 
>>> class FieldTracker(object):
...   def patch_save(self, instance):
...     original_save = instance.save
...     def save(**kwargs):
...       ret = original_save(**kwargs)
...       print("Used patched save")
...       return ret
...     instance.save = save
... 
>>> class Model(object):
...   name_field = 'joe'
...   field_tracker = FieldTracker()
...   def __init__(self):
...     self.field_tracker.patch_save(self)
...   def save(self):
...     print("Used default save")
... 
>>> model = Model()
>>> model.save()
Used default save
Used patched save
>>> _model = dill.loads(dill.dumps(model))
>>> _model.save()
Used default save
Used patched save

迪尔还有some good tools帮助您了解当代码失败时导致 pickle 失败的原因。

关于python - 如何重构返回闭包的方法以使其可 pickle ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19406097/

相关文章:

python - Telebot + Celery + pytransitions : response to task

Python:存储大数据结构

Python:用一些不可 pickle 的项目 pickle 字典

python - 如何减去 Pandas Dataframe 中的两个日期时间值

python - 按数字和字母顺序对两个元素元组的列表进行排序

python - 如何在 Python 脚本中嵌入 AppleScript?

python - Tensorflow Visual Studio 导入错误

process - Keras "pickle_safe": What does it mean to be "pickle safe", 或者 Python 中的 "non picklable"?

python - 读取 pickle 文件时出现 AttributeError

python - 在Python中将大字典存储到文件中