Python 2.2GB JSON文件解析不一致
我试图解码一个大的utf-8JSON文件(2.2GB)。我按如下方式加载文件:Python 2.2GB JSON文件解析不一致,python,json,unicode,utf-8,Python,Json,Unicode,Utf 8,我试图解码一个大的utf-8JSON文件(2.2GB)。我按如下方式加载文件: f = codecs.open('output.json', encoding='utf-8') data = f.read() 如果我尝试执行以下任一操作:json.load、json.load或json.JSONDecoder().raw_decode,我会得到错误: ------------------------------------------------------------------------
f = codecs.open('output.json', encoding='utf-8')
data = f.read()
如果我尝试执行以下任一操作:json.load
、json.load
或json.JSONDecoder().raw_decode
,我会得到错误:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-40-fc2255017b19> in <module>()
----> 1 j = jd.decode(data)
/usr/lib/python2.7/json/decoder.pyc in decode(self, s, _w)
367 end = _w(s, end).end()
368 if end != len(s):
--> 369 raise ValueError(errmsg("Extra data", s, end, len(s)))
370 return obj
371
ValueError: Extra data: line 1 column -2065998994 - line 1 column 2228968302
(char -2065998994 - 2228968302)
所以我应该是64位的,整数大小应该不是问题。但是,如果我运行:
jd = json.JSONDecoder()
len(data) # 2228968302
j = jd.raw_decode(data)
j[1] # 2228968302
raw\u decode
返回的元组中的第二个值是字符串的结尾,因此raw\u decode
似乎解析整个文件,结尾似乎没有垃圾
那么,我是否应该用json做些不同的事情?
raw\u decode
是否实际解码了整个文件?为什么json.load
失败了?我想将此作为注释添加,但是注释中的格式化功能太有限了
盯着源代码
raise ValueError(errmsg("Extra data", s, end, len(s)))
调用此函数:
def errmsg(msg, doc, pos, end=None):
...
fmt = '{0}: line {1} column {2} - line {3} column {4} (char {5} - {6})'
return fmt.format(msg, lineno, colno, endlineno, endcolno, pos, end)
格式的(char{5}-{6})
部分是您显示的错误消息的这一部分:
(char -2065998994 - 2228968302)
因此,在errmsg()
中,pos
是-2065998994,end
是222896802。瞧!;-):
也就是说,pos
和end
是“真正”相同的。从调用errmsg()
的位置返回,这意味着end
和len
实际上也是相同的-但是end
被视为32位有符号整数end
依次来自正则表达式匹配对象的end()
方法
因此,这里真正的问题似乎是regexp引擎中的32位限制/假设。我鼓励你
稍后:回答您的问题,是的,
raw\u decode()
正在解码整个文件。其他方法调用原始解码()
,但随后添加(失败!)健全性检查。您运行的是哪种系统?22亿对于带符号的32位整数来说太大了,异常详细信息中的负数表明您在这方面遇到了问题。如果不查看底层代码,我会猜测函数会将输入转换为字符串,并且它们在处理该大小的字符串时会出现溢出问题。“原始”版本可能没有,因此能够解析整个内容。@TimPeters我将此添加到我的问题中,但我使用的是64位体系结构。@TimPeters是的,但从raw_decode返回的索引表示解码的文档结尾是字符串的最后一个索引。@MrFooz我刚刚运行了一个调试器:s是unicode,end是int。
(char -2065998994 - 2228968302)
>>> pos = -2065998994
>>> end = 2228968302
>>> 2**32 + pos
2228968302L
>>> 2**32 + pos == end
True