pickle、copy_reg 为缺失的属性提供默认值的一个问题

2018-08-11 19:40:51 +08:00
 joeHuang

我电脑的 python 是2.7.10,在看picklecopy_reg为缺失的属性提供默认值的时候遇到了一个问题,具体如下:

  1. 先把仅有两个属性的GameState创建对象,并做序列化操作,保存到文件里。
  2. 然后GameState类新增加了属性point,这里用copy_reg来注册相应的行为,再进行反序列化操作

问题:在进行反序列操作后,新的属性没有被构造。这里如果序列化操作不保存到文件,整个操作又能正常,而不管是从文件里读还是strpickle实际调用的函数是一样的。找不到具体原因。求大神指点。

# 对应第一步
class GameState(object):
    def __init__(self):
        self.level = 0
        self.lives = 4

state = GameState()
state.level += 1
state.lives -= 1
print state.__dict__
'''
{'lives': 3, 'level': 1}
'''

import pickle
state_path = './game_state.pickle'
with open(state_path, 'wb') as f:
    pickle.dump(state, f)
# 对应第二步
class GameState(object):
    def __init__(self, level=0, lives=4, point=0):
        self.level = level
        self.lives = lives
        self.point = point

def pickle_obj(obj):
    kwargs = obj.__dict__
    return unpickle_obj, (kwargs,)

def unpickle_obj(kwargs):
    return GameState(**kwargs)

import copy_reg
copy_reg.pickle(GameState, pickle_obj)

import pickle
state_path = './game_state.pickle'
with open(state_path, 'rb') as f:
    state_after = pickle.load(f)
print state_after.__dict__
'''
{'lives': 3, 'level': 1}
'''
1694 次点击
所在节点    Python
2 条回复
joeHuang
2018-08-12 22:20:41 +08:00
昨天在 Python3.6 下试了下也有一样的问题。
joeHuang
2018-08-13 15:59:01 +08:00
找到原因了。正确的使用方式应该是第一次创建类的时候,就进行注册。
~~~python
class GameState(object):
def __init__(self):
self.level = 0
self.lives = 4

def pickle_obj(obj):
kwargs = obj.__dict__
return unpickle_obj, (kwargs,)

def unpickle_obj(kwargs):
return GameState(**kwargs)

import copy_reg
copy_reg.pickle(GameState, pickle_obj)

state = GameState()
state.level += 2
state.lives -= 3
print state.__dict__
'''
{'lives': 1, 'level': 2}
'''

import pickle
state_path = './game_state_v2.pickle'

with open(state_path, 'wb') as f:
pickle.dump(state, f)

class GameState(object):
def __init__(self, level=0, lives=4, point=0):
self.level = level
self.lives = lives
self.point = point

with open(state_path, 'rb') as f:
state_after = pickle.load(f)
print state_after.__dict__
'''
{'point': 0, 'lives': 1, 'level': 2}
'''
~~~

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/478910

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX