Python 3.6酸洗自定义程序

我有一些AA对象,它有自己的方法进行pickle,将其custom_module.customPickle(A) ,它接受A一个实例并返回一个序列化字符串。 我也有包含A每个B类对象的列表。

我需要腌制清单,但酸洗A会给出一些难以解决的错误。 但是, A有自己的方法来腌制。

我可以在类B实现__reduce__()方法,以便它调用custom_module.customPickle(A) 。 但我怎么能这样做,让pickle能够有效地序列化B


对象A是一个music21.stream ,对象B是一个自定义对象。 自定义序列化函数是music21.converter.freezeStr(streamObj, fmt=None) ,unpickle函数应该是music21.converter.thawStr(strData)


您可以使用copyreg模块注册用于酸洗和取消打印的自定义功能; 你注册的函数就像类中的__reduce__方法一样。

如果返回一个(unpickle_function, state)的元组,那么将调用已注册的unpickle_function callable来重新取消它的状态作为参数,因此您可以在其中使用您的music21.converter.thawStr()函数:

import copyreg
import music21.converter
import music21.stream


def pickle_music21_stream(stream_obj):
    return music21.converter.thawStr, (music21.converter.freezeStr(stream_obj),)

copyreg.pickle(music21.stream.Stream, pickle_music21_stream)

(在最近的Python版本中, copyregconstructor参数被忽略)

这为这些对象注册一个全局处理程序。 您也可以使用每个pickler的调度表,参见[* Dispatch Tables关于如何注册一个表。

现在,在酸洗时,遇到Stream的任何实例时,将使用handle_stream()函数来生成序列化,并且将使用thawStr()函数来再次取消该数据。

但是, music21.converter函数本身使用pickle。 他们有效地打包和清理流,然后pickle生成的Stream实例。 然后这将调用自定义处理程序,并且您有一个无限循环。

解决方法是使用自定义调度表来处理酸洗和拆卸。 避免在这种情况下使用copyreg ,因为它会设置一个全局钩子,每次Stream对象被酸洗时都会递归调用它。

您自己的泡菜基础设施需要使用自定义pickler:

import copyreg
import io
import pickle
import music21.converter
import music21.stream


def pickle_music21_stream(stream_obj):
    return music21.converter.thawStr, (music21.converter.freezeStr(stream_obj),)


def dumps(obj):
    f = io.BytesIO()
    p = pickle.Pickler(f)
    p.dispatch_table = copyreg.dispatch_table.copy()
    p.dispatch_table[music21.stream.Stream] = pickle_music21_stream
    p.dump(obj)
    return f.getvalue()


def loads(data):
    return pickle.loads(data)  # hook is registered in the pickle data

这里只有在您自己的数据结构中找到Stream实例时,才会调用自定义函数。 music21例程使用全局pickle.dumps()pickle.loads()函数,并且不会使用相同的钩子。

链接地址: http://www.djcxy.com/p/64831.html

上一篇: Python 3.6 pickling custom procedure

下一篇: Pickling and Unpickling a dynamically generated class