2013-10-07 32 views
6

大きなutf-8 jsonファイル(2.2 GB)をデコードしようとしています。私はそうのようなファイルを読み込む:2.2GB JSONファイルが一貫して解析されない

f = codecs.open('output.json', encoding='utf-8') 
data = f.read() 

Iのいずれかを実行しようとした場合:

--------------------------------------------------------------------------- 
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) 


uname -mx86_64

を示しています json.loadjson.loadsまたは json.JSONDecoder().raw_decode私はエラーを取得します
> python -c 'import sys;print("%x" % sys.maxsize, sys.maxsize > 2**32)' 
('7fffffffffffffff', True)` 

だから私は64ビットでなければならず、整数のサイズは問題ではないはずです。私が実行した場合

しかし、:

jd = json.JSONDecoder() 
len(data) # 2228968302 
j = jd.raw_decode(data) 
j[1] # 2228968302 

raw_decodeで返されるタプルの第二の値が文字列の末尾があるので、raw_decodeは、一見無ゴミでファイル全体を解析しているようです終わり。

だから、私はjsonとは違ったやり方をしているはずですか? raw_decodeは実際にファイル全体をデコードしていますか? json.load(s)はなぜ失敗しますか?

+2

どのようなシステムを実行していますか? 2。符号付き32ビット整数の場合、20億は大きすぎます。例外詳細の負の数値は、問題が発生していることを示唆しています。 –

+0

基礎となるコードを見ることなく、関数が入力を文字列に変換し、そのサイズの文字列を処理しようとするとオーバーフローの問題があることを推測します。 「生の」バージョンはおそらくそうではないので、すべてを解析することができます。 – Gabe

+0

@TimPeters私はこれを私の質問に追加しましたが、私は64ビットアーキテクチャを採用しています。 –

答えて

9

これをコメントとして追加しますが、コメントの書式設定機能はあまりにも制限されています。ソースコードを見つめ

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は2228968302です。見てください! ;-):

>>> pos = -2065998994 
>>> end = 2228968302 
>>> 2**32 + pos 
2228968302L 
>>> 2**32 + pos == end 
True 

posendは "本当に" と同じです、です。そこからerrmsg()が呼び出されたのは、endlen(s)が実際に同じであることを意味しますが、endは32ビット符号付き整数と見なされています。 endは、正規表現一致オブジェクトのend()メソッドから順番に取得されます。

ここで本当の問題は、正規表現エンジンでの32ビットの制限/仮定のようです。私はあなたにopen a bug reportをお勧めします!

後で:質問に答えて、はい、raw_decode()がファイル全体をデコードしています。他の方法raw_decode()を呼び出しますが、その後(失敗!)健全性チェックを追加してください。

関連する問題