Python 3.6 酸洗自定义程序
Python 3.6 pickling custom procedure
我有一些 class A
的对象,它们有自己的 pickle 方法,称它为 custom_module.customPickle(A)
,它采用 A
和 [=41 的实例=] 序列化字符串。
我还有每个 class B
的对象列表,其中包含 A
.
我需要 pickle 列表,但是 pickling A
给出了一些难以解决的错误。但是,A
有自己的腌制方法。
我可以在 class B
中实现 __reduce__()
方法,以便它调用 custom_module.customPickle(A)
。但是我该怎么做才能使 pickle
能够有效地序列化 B
?
对象 A
是一个 music21.stream
,对象 B
是一个自定义对象。自定义序列化函数为music21.converter.freezeStr(streamObj, fmt=None)
and the unpickle function should be music21.converter.thawStr(strData)
您可以在 class 上使用 copyreg
module to register custom functions for pickling and unpickling; the function you register acts like a __reduce__
method。
如果你 return 一个 (unpickle_function, state)
的元组,那么注册的 unpickle_function
可调用函数将被调用以再次解开它,以状态作为参数,所以你可以使用你的 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)
(copyreg
的 constructor
参数在最近的 Python 版本中被忽略)
这会为这些对象注册一个全局 处理程序。您还可以为每个 pickler 使用一个 dispatch table,请参阅 [*Dispatch Tables 了解如何注册一个。
现在,当 pickling 遇到 Stream
的任何实例时,handle_stream()
函数用于生成序列化,thawStr()
函数将用于再次对该数据进行 unpickle .
但是,music21.converter
函数本身使用 pickle。他们有效地打包和清理流,然后腌制生成的 Stream
实例。然后这将调用自定义处理程序,并且你有一个无限循环。
解决方法是使用自定义 dispatch table 来处理 pickling 和 unpickling。在这种情况下避免使用 copyreg
,因为它设置了一个全局挂钩,每次 Stream
对象被 pickle 时都会递归调用该挂钩。
您自己的 pickle 基础设施需要使用自定义 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()
函数,不会使用相同的钩子。
我有一些 class A
的对象,它们有自己的 pickle 方法,称它为 custom_module.customPickle(A)
,它采用 A
和 [=41 的实例=] 序列化字符串。
我还有每个 class B
的对象列表,其中包含 A
.
我需要 pickle 列表,但是 pickling A
给出了一些难以解决的错误。但是,A
有自己的腌制方法。
我可以在 class B
中实现 __reduce__()
方法,以便它调用 custom_module.customPickle(A)
。但是我该怎么做才能使 pickle
能够有效地序列化 B
?
对象 A
是一个 music21.stream
,对象 B
是一个自定义对象。自定义序列化函数为music21.converter.freezeStr(streamObj, fmt=None)
and the unpickle function should be music21.converter.thawStr(strData)
您可以在 class 上使用 copyreg
module to register custom functions for pickling and unpickling; the function you register acts like a __reduce__
method。
如果你 return 一个 (unpickle_function, state)
的元组,那么注册的 unpickle_function
可调用函数将被调用以再次解开它,以状态作为参数,所以你可以使用你的 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)
(copyreg
的 constructor
参数在最近的 Python 版本中被忽略)
这会为这些对象注册一个全局 处理程序。您还可以为每个 pickler 使用一个 dispatch table,请参阅 [*Dispatch Tables 了解如何注册一个。
现在,当 pickling 遇到 Stream
的任何实例时,handle_stream()
函数用于生成序列化,thawStr()
函数将用于再次对该数据进行 unpickle .
但是,music21.converter
函数本身使用 pickle。他们有效地打包和清理流,然后腌制生成的 Stream
实例。然后这将调用自定义处理程序,并且你有一个无限循环。
解决方法是使用自定义 dispatch table 来处理 pickling 和 unpickling。在这种情况下避免使用 copyreg
,因为它设置了一个全局挂钩,每次 Stream
对象被 pickle 时都会递归调用该挂钩。
您自己的 pickle 基础设施需要使用自定义 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()
函数,不会使用相同的钩子。