12

当我尝试打开时,我有一个 1.7 GB 的 JSON 文件,json.load()然后它给出了内存错误,如何在 python 中读取 JSON 文件?

我的 JSON 文件是一个包含特定键的大型对象数组。

编辑:好吧,如果它只是一大堆对象并且事先知道对象的结构,那么就不需要使用我们可以逐行读取它的工具。一行将只包含数组的一个元素。我注意到这是 json 文件的存储方式,对我来说它的工作原理是:

>>>for line in open('file.json','r').readline():
...    do something with(line) 
4

5 回答 5

14

您需要一个增量 json 解析器,如yajl及其 python 绑定之一。增量解析器从输入中读取尽可能少的内容,并在解码有意义的内容时调用回调。例如,要从一个大的 json 文件中只提取数字:

class ContentHandler(YajlContentHandler):
    def yajl_number(self, ctx, val):
         list_of_numbers.append(float(val))

parser = YajlParser(ContentHandler())
parser.parse(some_file)

有关更多信息,请参阅http://pykler.github.com/yajl-py/

于 2012-05-23T07:53:04.010 回答
4

我在yajl库周围找到了另一个 python 包装器,即ijson

由于以下原因,它对我来说比yajl-py更有效:

  • yajl-py 没有在我的系统上检测到 yajl 库,我必须破解代码才能使其工作
  • ijson 代码更紧凑,更易于使用
  • ijson 可以与 yajl v1 和 yajl v2 一起使用,它甚至有纯 python yajl 替换
  • ijson 有非常好的 ObjectBuilder,它不仅可以帮助从解析的流中提取事件,还可以提取有意义的子对象,并且在您指定的级别
于 2015-04-17T22:25:23.590 回答
0

我已经将 Dask 用于大型遥测 JSON-Lines 文件(换行符分隔)......
Dask 的好处是它为您做了很多工作。
有了它,您可以读取数据、处理数据并写入磁盘,而无需将其全部读入内存。
Dask 还将为您并行化并使用多个内核(线程)...

有关 Dask 袋的更多信息:
https ://examples.dask.org/bag.html

import ujson as json #ujson for speed and handling NaNs which are not covered by JSON spec
import dask.bag as db

def update_dict(d):
    d.update({'new_key':'new_value', 'a':1, 'b':2, 'c':0})
    d['c'] = d['a'] + d['b']
    return d

def read_jsonl(filepaths):
    """Read's a JSON-L file with a Dask Bag

    :param filepaths: list of filepath strings OR a string with wildcard
    :returns: a dask bag of dictionaries, each dict a JSON object
    """
    return db.read_text(filepaths).map(json.loads)



filepaths = ['file1.jsonl.gz','file2.jsonl.gz']
#OR
filepaths = 'file*.jsonl.gz' #wildcard to match multiple files

#(optional) if you want Dask to use multiple processes instead of threads
# from dask.distributed import Client, progress
# client = Client(threads_per_worker=1, n_workers=6) #6 workers for 6 cores
# print(client)

#define bag containing our data with the JSON parser
dask_bag = read_jsonl(filepaths)

#modify our data
#note, this doesn't execute, it just adds it to a queue of tasks
dask_bag.map(update_dict)

#(optional) if you're only reading one huge file but want to split the data into multiple files you can use repartition on the bag
# dask_bag = dask_bag.repartition(10)

#write our modified data back to disk, this is when Dask actually performs execution
dask_bag.map(json.dumps).to_textfiles('file_mod*.jsonl.gz') #dask will automatically apply compression if you use .gz
于 2020-10-28T23:27:21.373 回答
0

json当从本地磁盘访问大数据文件时,我发现 yajl(因此 ijson)比模块慢得多。当与 Cython 一起使用时,这是一个声称比 yajl/ijson 性能更好的模块(仍然比 慢json):

http://pietrobattiston.it/jsaone

正如作者指出的那样,性能可能比json通过网络接收文件时更好,因为增量解析器可以更快地开始解析。

于 2015-08-12T21:15:09.963 回答
0

对于简单的用途(即遍历顶级数组中的项目),json-stream-parser看起来不错(我没有使用它)。它似乎是一个独立的 JSON 解析器,用 234 行纯 Python 从头开始​​实现。

它不需要将 JSON 存储为“每行一个对象”或类似的东西。JSON 可以是一行,也可以有换行,没关系。

用法:

import sys
from json_stream_parser import load_iter
for obj in load_iter(sys.stdin):
    print(obj)
于 2020-05-06T14:11:27.220 回答