파이썬에서 큰 json 파일을로드하는 메모리 효율적이고 빠른 방법이 있습니까?
500MB의 json 파일이 있습니다. "사소한"json.load를 사용하여 콘텐츠를 한 번에로드하면 많은 메모리가 소모됩니다.
파일을 부분적으로 읽는 방법이 있습니까? 텍스트, 줄로 구분 된 파일이면 줄을 반복 할 수 있습니다. 나는 그것에 비유를 찾고있다.
어떤 제안? 감사
짧은 대답 : 아니요.
json 파일을 올바르게 분할하려면 json 객체 그래프에 대한 자세한 지식이 필요합니다.
그러나이 지식이 있다면 json 파일을 래핑하고 적절한 청크를 뱉어내는 파일 류 객체를 구현할 수 있습니다.
예를 들어, json 파일이 객체의 단일 배열이라는 것을 알고 있다면 json 파일을 래핑하고 배열의 청크를 반환하는 생성기를 만들 수 있습니다.
json 파일의 청킹을 올바르게하려면 문자열 콘텐츠 구문 분석을 수행해야합니다.
당신의 json 콘텐츠를 생성하는 것이 무엇인지 모르겠습니다. 가능하다면 하나의 거대한 파일 대신 관리 가능한 여러 파일을 생성하는 것을 고려할 것입니다.
더 나은 답을 가진이 질문에 대한 중복이 있습니다. ijson 을 제안하는 https://stackoverflow.com/a/10382359/1623645를 참조 하십시오 .
최신 정보:
나는 그것을 시험해 보았고 ijson은 SAX가 XML에 대해 무엇인지 JSON입니다. 예를 들어 다음과 같이 할 수 있습니다.
import ijson
for prefix, the_type, value in ijson.parse(open(json_file_name)):
print prefix, the_type, value
어디 prefix
json으로 트리의 점으로 구분 된 인덱스 (키 이름 그들에 도트가 있다면? 나는 ... 그게 너무, 자바 스크립트에 대한 나쁜 것 같아요 무슨 일)이며, theType
색소폰과 같은 이벤트 중 하나를 설명 'null', 'boolean', 'number', 'string', 'map_key', 'start_map', 'end_map', 'start_array', 'end_array'
하고 value
있다 객체의 값 또는 지도 / 배열 시작 / 종료와 같은 이벤트 인 None
경우the_type
프로젝트에 일부 독 스트링이 있지만 전역 문서가 충분하지 않습니다. 나는 내가 ijson/common.py
찾고있는 것을 찾기 위해 파헤쳐 야했다 .
따라서 문제는 각 파일이 너무 크다는 것이 아니라 파일이 너무 많아서 메모리에 추가되는 것 같습니다. Python의 가비지 수집기는 필요하지 않은 참조를 유지하지 않는 한 괜찮습니다. 추가 정보없이 정확히 무슨 일이 일어나고 있는지 말하기는 어렵지만 몇 가지 시도해 볼 수 있습니다.
코드를 모듈화하십시오. 다음과 같이하십시오.
for json_file in list_of_files: process_file(json_file)
당신이 작성하는 경우
process_file()
는 전역 상태에 의존하지 않고, 전역 상태를 변경하지 않는 것과 같은 방식으로, 가비지 컬렉터는 그 일을 할 수 있어야합니다.별도의 프로세스에서 각 파일을 처리합니다. 모든 JSON 파일을 한 번에 구문 분석하는 대신 하나만 구문 분석하는 프로그램을 작성하고 각 파일을 셸 스크립트 또는 .NET을 통해 스크립트를 호출하는 다른 Python 프로세스에서 전달
subprocess.Popen
합니다. 이것은 다소 덜 우아하지만 다른 것이 작동하지 않으면 한 파일에서 다음 파일로 오래된 데이터를 유지하지 않도록 보장합니다.
도움이 되었기를 바랍니다.
예.
당신은 사용할 수 있습니다 jsonstreamer 을 수행 할 수 있습니다 SAX와 같은 푸시 파서 내가 쓴 것을 당신은 임의의 크기의 덩어리를 구문 분석 할 수 있습니다 여기를 얻을 수 및 예제에 대한 README를 체크 아웃. 'C'yajl 라이브러리를 사용하기 때문에 빠릅니다.
메모리 부족에 대해 언급하면서 실제로 메모리를 관리하고 있는지 질문해야합니다. 새 개체를 읽기 전에 "del"키워드를 사용하여 이전 개체를 제거하고 있습니까? 파이썬은 당신이 그것을 제거한다면 절대로 어떤 것을 메모리에 조용히 보관해서는 안됩니다.
"가비지 수집기는 메모리를 해제해야합니다."
옳은.
그렇지 않기 때문에 다른 것이 잘못되었습니다. 일반적으로 무한 메모리 증가의 문제는 전역 변수입니다.
모든 전역 변수를 제거하십시오.
모든 모듈 수준 코드를 더 작은 함수로 만듭니다.
또 다른 아이디어는 MongoDB와 같은 문서 저장소 데이터베이스에로드하는 것입니다. JSON의 큰 덩어리를 잘 처리합니다. JSON을로드하는 데 동일한 문제가 발생할 수 있지만 파일을 한 번에 하나씩로드하여 문제를 방지하십시오.
경로가 작동하는 경우 클라이언트를 통해 JSON 데이터와 상호 작용할 수 있으며 잠재적으로 전체 blob을 메모리에 보관할 필요가 없습니다.
@codeape 외에도
처리중인 JSON Blob의 구조를 파악하는 데 도움이되는 사용자 지정 json 파서를 작성해 보겠습니다. 키 이름 만 인쇄하십시오. 계층 구조 트리를 만들고 청크 방법을 스스로 결정하십시오. 이렇게하면 @codeape가 제안하는 작업을 수행 할 수 있습니다. 파일을 더 작은 덩어리로 나눌 수 있습니다.
ijson 을 사용하여 수행 할 수 있습니다 . ijson의 작업은 위의 답변에서 Jim Pivarski 에 의해 매우 잘 설명되었습니다 . 아래 코드는 파일을 읽고 목록에서 각 json을 인쇄합니다. 예를 들어 파일 내용은 다음과 같습니다.
[{"name": "rantidine", "drug": {"type": "tablet", "content_type": "solid"}},
{"name": "nicip", "drug": {"type": "capsule", "content_type": "solid"}}]
아래 방법을 사용하여 배열의 모든 요소를 인쇄 할 수 있습니다.
def extract_json(filename):
with open(filename, 'rb') as input_file:
jsonobj = ijson.items(input_file, 'item')
jsons = (o for o in jsonobj)
for j in jsons:
print(j)
참고 : 'item'은 ijson에서 제공하는 기본 접두사입니다.
조건에 따라 특정 json에만 액세스하려면 다음과 같이 할 수 있습니다.
def extract_tabtype(filename):
with open(filename, 'rb') as input_file:
objects = ijson.items(input_file, 'item.drugs')
tabtype = (o for o in objects if o['type'] == 'tablet')
for prop in tabtype:
print(prop)
이것은 유형이 태블릿 인 json 만 인쇄합니다.
'IT박스' 카테고리의 다른 글
내 콤보 상자에서 마우스 휠 스크롤을 방지하려면 어떻게합니까? (0) | 2020.12.30 |
---|---|
파이썬에서 배열 / 사전 목록을 어떻게 만들 수 있습니까? (0) | 2020.12.30 |
VBA (Excel)에서 오류를 올바르게 처리 (0) | 2020.12.30 |
C / C ++ 파일에서 Android NDK의 컴파일을 감지하는 방법은 무엇입니까? (0) | 2020.12.30 |
스마트 포인터보다 원시 포인터를 언제 사용해야합니까? (0) | 2020.12.30 |