Python pickle 丢失数据

2 投票
2 回答
1588 浏览
提问于 2025-04-16 12:36

我有4个嵌套的类,下面是个例子:

class GameInfo:
    id = ""
    round = ""
    # ... etc

class Opponent:
    game_info = GameInfo()
    name = ""
    # ...

class Tournament:
    opponent_list = [] # list of Opponent objects
    # ...

class Journal(db.Model):
    picked_tournament = db.BlobProperty()  # here I put picked Tournament object

问题是:当我在Journal中反序列化pickled_tournament时,GameInfo里的所有数据都丢失了。也就是说,opponent.name显示的值是正确的,但opponent.game_info.id却是空字符串。

我使用Google App Engine的数据存储来保存数据,picked_tournament是存储在BlobProperty()里的。为了序列化数据,我调用:journal.picked_tournament = pickle.dumps(tournament)。加载数据时,我使用:tournament = pickle.loads(journal.picked_tournament)

为什么pickle没有深入到超过2层的地方呢?

更新:数据是这样设置的:

gi = GameInfo()
gi.id = "1234"
opp = Opponent()
opp.name = "John"
opp.game_info = gi
t = Tournament()
t.opponent_list.append(opp)
# etc...

更新2:我刚发现,如果数据库是sqlite3,开发服务器上一切正常,但在没有sqlite3的情况下和在appspot上就不行了!

2 个回答

1

根据App Engine的文档(我还没有实际尝试过),可以试着把pickle数据设置为一个blob:

journal.picked_tournament = db.Blob(pickle.dumps(tournament))

如果这样不行,检查一下journal.picked_tournament是否等于pickle.dumps(tournament)。

3

在你的 Opponent 类的构造函数里,你只创建了一个 GameInfo 的实例,这个实例被所有的 Opponent 类的对象共享。举个例子:

>>> o1 = Opponent()
>>> o1.game_info.id = 5
>>> o2 = Opponent()
>>> o2.game_info.id
5

其实,你应该为每一个 Opponent 的实例单独创建一个 GameInfo。你可以在构造函数里这样初始化:

class Opponent:
    def __init__(self):
        game_info = GameInfo()

另外,既然现在已经不是90年代了,你真的应该使用 新风格的类

撰写回答