我试图打开超过一定大小的搁置持久文件时遇到此异常,这实际上非常小(<1MB),但我不确定确切的数字在哪里。现在,我知道pickle有点像python的私生子,搁置并不被认为是一个特别强大的解决方案,但它恰好解决了我的问题(理论上),我无法找到原因这个例外。
Traceback (most recent call last):
File "test_shelve.py", line 27, in <module>
print len(f.keys())
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shelve.py", line 101, in keys
return self.dict.keys()
SystemError: Negative size passed to PyString_FromStringAndSize
我可以一致地重现它,但我在谷歌上找不到太多东西。这是一个可以重现的脚本。
import shelve
import random
import string
import pprint
f = shelve.open('test')
# f = {}
def rand_list(list_size=20, str_size=40):
return [''.join([random.choice(string.ascii_uppercase + string.digits) for j in range(str_size)]) for i in range(list_size)]
def recursive_dict(depth=3):
if depth==0:
return rand_list()
else:
d = {}
for k in rand_list():
d[k] = recursive_dict(depth-1)
return d
for k,v in recursive_dict(2).iteritems():
f[k] = v
f.close()
f = shelve.open('test')
print len(f.keys())
答案 0 :(得分:2)
如果我将深度从2更改为1,或者如果我在python 3下运行(在修复print
语句并使用items()
而不是iteritems()
后),则代码“有效” 。但是,在迭代recursive_dict()
的返回值时,键列表显然不是找到的键集。
shelve
文档中的以下限制可能适用(强调我的):
选择使用哪个数据库包(例如dbm,gdbm或bsddb)取决于可用的接口。因此,使用dbm直接打开数据库是不安全的。 数据库(不幸的是)受到dbm的限制,如果使用的话 - 这意味着存储在数据库中的对象的(腌制表示)应该相当小,并且在极少数情况下,密钥冲突可能导致数据库拒绝更新。
答案 1 :(得分:2)
关于错误本身:
在网络上传播的想法是数据大小超过最大 该机器上可能的整数(最大的32位(带符号)整数) 是2 147 483 647),被Python解释为负面大小。
您的代码与2.7.3
一起运行,因此可能是一个固定的错误。