gpt4 book ai didi

python-3.x - 协议(protocol) = 4 pickle (python 3.7): Keyerror when load dicts with the same key inside

转载 作者:行者123 更新时间:2023-12-03 10:08:38 32 4
gpt4 key购买 nike

我正在运行由 anaconda 在 Mac 上安装的 python3.7.9-64bit。
刚好遇到三个问题。
(虽然我写了 fix_import=False,但改变它并没有任何区别)
第一个问题 , 如果两个具有相同键的字典在一个文件中被 pickle ,加载第二个字典将 引发 KeyError .

import pickle

d1={"a":1}# if two dicts has the same key
d2={"a":0}# does not matter what value is stored.

tmpf=open("deleteThis","wb")
pkl=pickle.Pickler(tmpf,protocol=4,fix_imports=False)
pkl.dump(d1)
pkl.dump(d2)
tmpf.close()

tmpf2=open("deleteThis","rb")
td1=pickle.load(tmpf2)
td2=pickle.load(tmpf2)# KeyError 1
第二题 ,虽然它可能与第一个有关,但如果第二个字典里面有一个字典 D 与第一个字典共享相同的键,那么 D的关键变化加载时。
d1={"a":1}
d2={"lll":{"a":2} }# this "a" will always be "lll"

tmpf=open("deleteThis","wb")
pkl=pickle.Pickler(tmpf,protocol=4,fix_imports=True)
pkl.dump(d1)
pkl.dump(d2)
tmpf.close()

tmpf2=open("deleteThis","rb")
td1=pickle.load(tmpf2)
td2=pickle.load(tmpf2)
print(td1,td2)# {'a': 1} {'lll': {'lll': 2}}
第三题 ,对我来说最具破坏性的是,如果有一个字典 get pickle.dump 并且第二个转储的字典有一个共享相同 key 的字典列表,则加载第二个字典 引发 KeyError .
d1={"b":0}
d2={ "l":[{"a":2} , {"a",3}] }

tmpf=open("deleteThis","wb")
pkl=pickle.Pickler(tmpf,protocol=4,fix_imports=True)
pkl.dump(d1)
pkl.dump(d2)
tmpf.close()

tmpf2=open("deleteThis","rb")
td1=pickle.load(tmpf2)
td2=pickle.load(tmpf2)# KeyError
这些问题只发生在 pickle( protocol=4 ) 上。 . protocol=3 没有任何问题
未知 python>3.8 或 protocl=5

最佳答案

您的问题的简短回答是使用 pickle.Unpickler() 加载你的 pickle 。
或者,不要使用 pickle.Pickler() .而是用 pickle.dump() 写每个 pickle 并用 pickle.load() 回读或 pickle.Unpickler() .
其中任何一个都可以解决您的问题。

我可以确认您所描述的相同问题在 Python 3.9.1 中对于协议(protocol)版本 4 和 5 都存在。
顺便说一句:请注意 {"a",3}在你的最后一个例子中是一个集合,而不是你想象的一个字典。然而,同样的错误会发生。
问题是 Pickler使用备忘录来缓存它已经 pickle 的数据。它通过避免多次存储相同的数据来使用它来节省结果文件的大小。备忘录在使用 Pickler 编写的所有 pickle 之间共享。 .Unpickler使用备忘录重建共享缓存数据的 pickle 对象。但是,pickle.load()不使用备忘录,因此无法找到 Pickler 的值。当它倾倒单个 pickle 时就记住了。

下面是一些代码来演示:

import pickle

d1 = {"b": 0}
d2 = {"l": [{"a": 2}, {"a": 3}]}

with open("deleteThis", "wb") as tmpf:
pkl = pickle.Pickler(tmpf, protocol=4)
for obj in d1, d2:
pkl.dump(obj)

# reload objects with Unpickler - will work.
with open("deleteThis", "rb") as tmpf:
unpkl = pickle.Unpickler(tmpf)
print('Using Unpickler')
while True:
try:
print(unpkl.load())
except EOFError:
break

# reload objects with pickle.load - might work, but won't here.
with open("deleteThis", "rb") as tmpf:
print('Using pickle.load()')
while True:
try:
print(pickle.load(tmpf))
except EOFError:
break
它的输出:
使用 Unpickler
{'b':0}
{'l': [{'a': 2}, {'a': 3}]}
使用 pickle.load()
{'b':0}
回溯(最近一次通话最后):
文件“/tmp/z.py”,第 26 行,在
打印(pickle.load(tmpf))
_pickle.UnpicklingError:在索引 6 处找不到备注值

关于python-3.x - 协议(protocol) = 4 pickle (python 3.7): Keyerror when load dicts with the same key inside,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65733209/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com