推荐学习书目
› Learn Python the Hard Way
Python Sites
› PyPI - Python Package Index
› http://diveintopython.org/toc/index.html
› Pocoo
值得关注的项目
› PyPy
› Celery
› Jinja2
› Read the Docs
› gevent
› pyenv
› virtualenv
› Stackless Python
› Beautiful Soup
› 结巴中文分词
› Green Unicorn
› Sentry
› Shovel
› Pyflakes
› pytest
Python 编程
› pep8 Checker
Styles
› PEP 8
› Google Python Style Guide
› Code Style from The Hitchhiker's Guide
joeHuang
V2EX  ›  Python

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

  •  
  •   joeHuang · Aug 11, 2018 · 2618 views
    This topic created in 2967 days ago, the information mentioned may be changed or developed.

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

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

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

    # 对应第一步
    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}
    '''
    
    2 replies  •  2018-08-13 15:59:01 +08:00
    joeHuang
        1
    joeHuang  
    OP
       Aug 12, 2018
    昨天在 Python3.6 下试了下也有一样的问题。
    joeHuang
        2
    joeHuang  
    OP
       Aug 13, 2018
    找到原因了。正确的使用方式应该是第一次创建类的时候,就进行注册。
    ~~~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}
    '''
    ~~~
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2398 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 11:45 · PVG 19:45 · LAX 04:45 · JFK 07:45
    ♥ Do have faith in what you're doing.