2014-06-16 2 views
4

큰 배열을 json 형식으로 인코딩 할 때 json.dump() 또는 json.dumps() 중 어느 것이 가장 효율적인지 알고 싶습니다.json.dumps()를 사용하여 MemoryError

json.dump()을 사용하는 예를 보여줄 수 있습니까?

사실 나는 ORM SQlAlchemy를 사용하여 MySQL 데이터베이스에서 많은 양의 데이터를 가져 오는 Python CGI를 만들고 일부 사용자가 처리를 트리거 한 후에 최종적으로 Json으로 변환하는 Array에 최종 출력을 저장합니다.

그러나와 JSON으로 변환 할 때 :

Traceback (most recent call last): 
    File "C:/script/cgi/translate_parameters.py", line 617, in  <module> 
f.write(json.dumps(mytab,default=dthandler,indent=4)) 
    File "C:\Python27\lib\json\__init__.py", line 250, in dumps 
    sort_keys=sort_keys, **kw).encode(obj) 
    File "C:\Python27\lib\json\encoder.py", line 209, in encode 
    chunks = list(chunks) 
MemoryError 

그래서, 내 생각 엔 덩어리로 데이터를 변환 json.dump()을 사용하고 있습니다 :

print json.dumps({'success': True, 'data': data}) #data is my array 

나는 다음과 같은 오류가 발생합니다. 이 작업을 수행하는 방법에 대한 아이디어가 있습니까?

json.dump() 이외의 다른 아이디어입니까?

+0

구현 세부 사항을 모르지만 '덤프 (dumps)'결과는 문자열로 출력됩니다.이 문자열은 빌드되어 메모리에 보관되어야합니다. '덤프 (dump) '는 스트리밍되어 메모리에 결과를 저장하지 않을 것으로 가정하는 파일에 기록합니다. – Joe

+0

'chunk'는'JSON.Encoder(). iterencode()'생성자에 의해 생성됩니다. 내 대답을 보라. –

답변

6

당신은 단순히 파일에

json.dump(mytab, f, default=dthandler, indent=4) 

에 의해이해야한다 "스트림"데이터를

f.write(json.dumps(mytab,default=dthandler,indent=4)) 

을 대체 할 수 있습니다.

+0

당신의 예제에서 mytab이 JSON-serialisable 객체 인'json '이라고 가정하더라도 이것은 작동하지 않습니다.dump()'는 어떤 객체를 덤핑하는지 알지 못합니다. 또한, 시도해도 큰 객체에 대해 'MemoryError'가 생성됩니다. –

+0

오른쪽 .. 인수로 mytab을 잊어 버렸습니다. 결정된. 메모리에 관해서는 더 효율적인 메모리 구현을 기대하는 다른 json 라이브러리를 시험해 볼 가치가있을 것입니다 ... – sebastian

+0

결국 내 답변을 게시하는 해결 방법을 발견했습니다 : –

3

JSON 모듈은 쓰기 전에 전체 JSON 문자열을 메모리에 할당하므로 MemoryError이 발생합니다.

이 문제를 해결하기 JSON.Encoder().iterencode()를 사용하려면이 한 번에 모든 것을 많은 작은 덩어리에 쓰기되지 않기 때문에

with open(filepath, 'w') as f: 
    for chunk in json.JSONEncoder().iterencode(object_to_encode): 
     f.write(chunk) 

그러나, 이것은 일반적으로 매우 시간이 걸릴 않습니다.


전용 케이스는 :

나는 dicts의 목록입니다 파이썬 객체를했다. 내가 JSON.dumps() 개별 개체하지만 덤핑 전체 목록 쓰기 속도를하려면 MemoryError를 생성, 나는 파일을 열고 수동으로 JSON 구분 작성 수

[ 
    { "prop": 1, "attr": 2 }, 
    { "prop": 3, "attr": 4 } 
    # ... 
] 

: 예처럼

with open(filepath, 'w') as f: 
    f.write('[') 

    for obj in list_of_dicts[:-1]: 
     json.dump(obj, f) 
     f.write(',') 

    json.dump(list_of_dicts[-1], f) 
    f.write(']') 

을 당신은 아마 수 JSON 객체 구조를 미리 아는 경우에는 이와 같은 것을 사용하십시오. 일반적으로는 JSON.Encoder().iterencode()을 사용하십시오.

+0

그게 바로'json.dump'가하는 일입니다 : https : // hg .python.org/cpython/file/v2.7.10/Lib/json/__ init __. py # l183 – sebastian

+0

큰 개체를 사용하면 iterencode()가 너무 느립니다. 메모리를 저장할 수있는 위치로 덩어리를 나누는 것이 가장 좋습니다 핸들을 한 번에 encode() 할 수 있습니다. –

관련 문제