2013-10-07 14 views
6

Büyük bir utf-8 json dosyasını (2.2 GB) çözümlemeye çalışıyorum. Ben şöyle dosyası yüklemek:2.2GB JSON dosyası tutarsız olarak ayrıştırılıyor

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

ben herhangi birini denerseniz:

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

gösterir: json.load, json.loads veya json.JSONDecoder().raw_decode hatası alıyorum
> python -c 'import sys;print("%x" % sys.maxsize, sys.maxsize > 2**32)' 
('7fffffffffffffff', True)` 

Yani 64 bit olmalı ve tamsayı boyutu bir sorun olmamalıdır. Ben çalıştırırsanız

Ancak:

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

raw_decode tarafından döndürülen demet içinde ikinci değer dize sonudur, bu raw_decode de görünüşte hiçbir çöp ile tüm dosyayı ayrıştırmak gibi görünüyor son.

Yani, json ile farklı bir şekilde yapmam gereken bir şey var mı? raw_decode aslında tüm dosyanın kodunu çözüyor mu? Neden json.load(s) başarısız oluyor?

+2

Ne tür bir sistem çalışıyorsunuz? 2.İmzalı bir 32 bit tam sayı için 2 milyar çok büyük ve istisna ayrıntısındaki negatif sayılar, bununla ilgili sorunlara yol açtığınızı gösterir. –

+0

Temel koda bakmadan, işlevlerin girdiyi bir dizeye dönüştürdüğünü ve bu boyuttaki bir dizeyi işlemeye çalışan taşma sorunlarının olduğunu tahmin edeceğim. "Ham" versiyon muhtemelen yok ve bu yüzden her şeyi ayrıştırabiliyor. – Gabe

+0

@TimPeters Bunu soruma ekledim, ancak 64 bit mimarideyim. –

cevap

9

Bunu bir yorum olarak eklemek istiyorum, ancak yorumlardaki biçimlendirme olanakları çok sınırlı. Kaynak kodu bakıyorum

,

raise ValueError(errmsg("Extra data", s, end, len(s))) 

aramalar bu işlevi:

(char -2065998994 - 2228968302) 
:

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) 

formatının (char {5} - {6}) parçası gösterdi hata mesajının bu parçasıdır

Yani, errmsg(), pos, -2065998994'tür. ve end, 2228968302'dir. ;-):

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

pos ve end "gerçekten" Aynı olmaları. errmsg()'un çağrıldığı yerden, yani end ve len(s) gerçekten aynıdır - ancak end 32 bit imzalı bir tamsayı olarak görüntüleniyor. end, sırayla bir düzenli ifade eşleme nesnesinin end() yönteminden gelir. Yani buradaki asıl sorun, regexp motorunda 32-bit bir sınırlama/varsayım gibi görünmektedir. Seni open a bug report'a davet ediyorum!

Daha sonra: sorularınızı yanıtlamak için, evet, raw_decode() tüm dosyanın kodunu çözüyor. Diğer yöntemler ,raw_decode()'u arar, ancak (arızalı!) Akıl denetimlerini sonradan ekler.