대용량 JSON 파일을 빠르고 효율적으로 로드할 수 있는 방법이 있습니까?
500MB의 json .을 'trival'을 json.load()
한 번에 콘텐츠를 로드하려면 많은 메모리가 필요합니다.
파일을 부분적으로 읽을 수 있는 방법이 있나요?텍스트, 행 구분 파일이라면 행에 걸쳐 반복할 수 있습니다.나는 그것에 대한 유추를 찾고 있다.
이 질문에는 더 나은 답을 가진 중복된 질문이 있었다.ijson을 제안하는 https://stackoverflow.com/a/10382359/1623645,을 참조하십시오.
업데이트:
ijson과 JSON의 관계는 SAX와 XML의 관계입니다.예를 들어, 다음과 같이 할 수 있습니다.
import ijson
for prefix, the_type, value in ijson.parse(open(json_file_name)):
print prefix, the_type, value
서 ''는prefix
는 JSON 트리의 도트로 구분된 인덱스입니다(키 이름에 도트가 있으면 어떻게 됩니까).Javascript에도 안 것 Javascript ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★)theType
SAX와 .SAX는 SAX의 입니다.'null', 'boolean', 'number', 'string', 'map_key', 'start_map', 'end_map', 'start_array', 'end_array'
, , , , 입니다.value
값 ""입니다.None
the_type
맵/어레이의 시작/종료와 같은 이벤트입니다.
프로젝트에는 일부 문서 문자열이 있지만 글로벌 문서가 부족합니다.난난 into into into into into 를 파고들지 않으면 .ijson/common.py
내가 찾던 걸 찾을 수 있었어
문제는 각 파일이 너무 크다는 것이 아니라 파일이 너무 많다는 것입니다.또한 이 파일들은 메모리에 축적되어 있는 것 같습니다.Python의 가비지 컬렉터는 불필요한 참조를 가지고 있지 않는 한 문제 없습니다.자세한 정보 없이는 정확히 무슨 일이 일어나고 있는지 알 수 없지만, 몇 가지 시도해 볼 수 있습니다.
코드를 모듈화합니다.다음과 같은 작업을 수행합니다.
for json_file in list_of_files: process_file(json_file)
process_file()
가비지 콜렉터는 글로벌 상태에 의존하지 않고 글로벌 상태를 변경하지 않는 방법으로 작업을 수행할 수 있어야 합니다.각 파일을 별도의 프로세스로 처리합니다.한 하는 것이 JSON을 를 호출하는 합니다.
subprocess.Popen
이 방법은 조금 덜 우아하지만 다른 방법이 없을 경우 오래된 데이터를 파일 간에 보관하지 않아도 됩니다.
이게 도움이 됐으면 좋겠다.
네.
제가 작성한 jsonstreamer SAX와 같은 push parser를 사용하면 임의의 크기의 청크를 해석할 수 있습니다.여기서 입수하여 README을 체크합니다.C야즐 라이브러리를 사용하기 때문에 빠릅니다.
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만 인쇄됩니다.
메모리 부족에 대한 당신의 언급에 대해 나는 당신이 실제로 메모리를 관리하고 있는지 의심해야 한다.새로운 오브젝트를 읽기 전에 오래된 오브젝트를 삭제하기 위해 "del" 키워드를 사용하고 있습니까?Python은 삭제해도 메모리에 묵묵히 저장해서는 안 됩니다.
갱신하다
기타 답변을 참조하여 조언을 얻으십시오.
2010년 원본 답변이 현재는 구식입니다.
간단한 답변: 아니요.
json 파일을 올바르게 분할하려면 json 객체 그래프에 대한 자세한 지식이 필요합니다.
그러나 이 지식이 있으면 json 파일을 랩하고 적절한 청크를 뱉어내는 파일과 같은 개체를 구현할 수 있습니다.
예를 들어 json 파일이 단일 개체 배열임을 알고 있는 경우 json 파일을 랩하고 어레이의 청크를 반환하는 생성기를 생성할 수 있습니다.
json 파일의 청킹을 올바르게 실시하려면 , 문자열 컨텐츠의 해석을 실시할 필요가 있습니다.
무엇이 당신의 json 콘텐츠를 생성하는지 모르겠습니다.가능하다면 하나의 큰 파일이 아니라 여러 개의 관리 가능한 파일을 생성하는 것을 검토하고 있습니다.
또 다른 아이디어는 MongoDB와 같은 문서 저장 데이터베이스에 로드하는 것입니다.JSON의 큰 얼룩에 잘 대처합니다.JSON을 로드하는 데 동일한 문제가 발생할 수 있지만 파일을 한 번에 하나씩 로드하여 문제를 방지하십시오.
패스가 기능하는 경우는, 클라이언트를 개입시켜 JSON 데이터와 대화할 수 있기 때문에, BLOB 전체를 메모리에 보존할 필요는 없습니다.
"가비지 컬렉터가 메모리를 해방해야 합니다."
맞아요.
그게 아니라서 뭔가 잘못됐어.일반적으로 무한 확장 메모리의 문제는 글로벌 변수입니다.
모든 글로벌 변수를 삭제합니다.
모듈 레벨의 모든 코드를 작은 함수로 만듭니다.
@codeape와 더불어
당신이 취급하고 있는 JSON blob의 구조를 알아내는 데 도움이 되는 커스텀 json 파서를 써 보겠습니다.키 이름만 출력합니다.계층 트리를 만들고 청크 방법을 결정합니다.이 방법으로 @codeape가 제안하는 것을 실행할 수 있습니다.파일을 작은 덩어리로 분할하는 등
JSON 파일을 CSV 파일로 해석하여 한 줄씩 해석할 수 있습니다.
import ijson
import csv
def convert_json(self, file_path):
did_write_headers = False
headers = []
row = []
iterable_json = ijson.parse(open(file_path, 'r'))
with open(file_path + '.csv', 'w') as csv_file:
csv_writer = csv.writer(csv_file, ',', '"', csv.QUOTE_MINIMAL)
for prefix, event, value in iterable_json:
if event == 'end_map':
if not did_write_headers:
csv_writer.writerow(headers)
did_write_headers = True
csv_writer.writerow(row)
row = []
if event == 'map_key' and not did_write_headers:
headers.append(value)
if event == 'string':
row.append(value)
따라서 단순히 json.load()를 사용하는 데 시간이 많이 걸립니다.대신, 키와 값 쌍을 사용하여 json 데이터를 한 줄씩 사전에 로드하고 해당 사전을 최종 사전에 추가하여 추가 분석에 도움이 되는 panda DataFrame으로 변환할 수 있습니다.
def get_data():
with open('Your_json_file_name', 'r') as f:
for line in f:
yield line
data = get_data()
data_dict = {}
each = {}
for line in data:
each = {}
# k and v are the key and value pair
for k, v in json.loads(line).items():
#print(f'{k}: {v}')
each[f'{k}'] = f'{v}'
data_dict[i] = each
Data = pd.DataFrame(data_dict)
#Data will give you the dictionary data in dataFrame (table format) but it will
#be in transposed form , so will then finally transpose the dataframe as ->
Data_1 = Data.T
언급URL : https://stackoverflow.com/questions/2400643/is-there-a-memory-efficient-and-fast-way-to-load-big-json-files
'programing' 카테고리의 다른 글
JSON을 데이터베이스로 사용할 수 있습니까? (0) | 2023.03.25 |
---|---|
스프링 부트 - 핸들을 휴지 상태로 전환 Session Factory (0) | 2023.03.25 |
요청된 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다(Angular).JS (0) | 2023.03.20 |
HOC - 기능 컴포넌트 (0) | 2023.03.20 |
하나의 컨트롤러를 2개의 다른 뷰에 재사용하는 방법 (0) | 2023.03.20 |