繁体   English   中英

如何使用 Python ijson 读取大型 JSON 文件?

[英]How to read a large JSON file using Python ijson?

我正在尝试解析一个大的 json 文件(数百个演出)以从其密钥中提取信息。 为简单起见,请考虑以下示例:

import random, string

# To create a random key 
def random_string(length):
        return "".join(random.choice(string.lowercase) for i in range(length))

# Create the dicitonary 
dummy = {random_string(10): random.sample(range(1, 1000), 10) for times in range(15)}

# Dump the dictionary into a json file 
with open("dummy.json", "w") as fp:
        json.dump(dummy, fp)

然后,我在 python 2.7 中使用 ijson 来解析文件:

file_name = "dummy.json"

with open(file_name, "r") as fp:

    for key in dummy.keys():

        print "key: ", key 

        parser = ijson.items(fp, str(key) + ".item")

        for number in parser:
            print number,

我期待检索列表中与 dic 键对应的所有数字。 但是,我得到了

IncompleteJSONError:不完整的 JSON 数据

我知道这篇文章: Using python ijson to read a large json file with multiple json objects ,但在我的例子中,我有一个格式正确的 json 文件,具有相对简单的架构。 关于如何解析它的任何想法? 谢谢你。

ijson有一个迭代器接口来处理大型 JSON 文件,允许延迟读取文件。 您可以以小块的形式处理文件并将结果保存在其他地方。

调用ijson.parse()产生三个值prefix, event, value

一些 JSON:

{
    "europe": [
      {"name": "Paris", "type": "city"},
      {"name": "Rhein", "type": "river"}
    ]
  }

代码:

import ijson


data = ijson.parse(open(FILE_PATH, 'r'))

for prefix, event, value in data:
    if event == 'string':
        print(value)

输出:

Paris
city
Rhein
river

参考: https ://pypi.python.org/pypi/ijson

示例json内容文件如下:里面有两个人的记录。 它也可能有 200 万条记录。

    [
      {
        "Name" : "Joy",
        "Address" : "123 Main St",
        "Schools" : [
          "University of Chicago",
          "Purdue University"
        ],
        "Hobbies" : [
          {
            "Instrument" : "Guitar",
            "Level" : "Expert"
          },
          {
            "percussion" : "Drum",
            "Level" : "Professional"
          }
        ],
        "Status" : "Student",
        "id" : 111,
        "AltID" : "J111"
      },
      {
        "Name" : "Mary",
        "Address" : "452 Jubal St",
        "Schools" : [
          "University of Pensylvania",
          "Washington University"
        ],
        "Hobbies" : [
          {
            "Instrument" : "Violin",
            "Level" : "Expert"
          },
          {
            "percussion" : "Piano",
            "Level" : "Professional"
          }
        ],
        "Status" : "Employed",
        "id" : 112,
        "AltID" : "M112"
      }
      }
    ]

我创建了一个生成器,它将每个人的记录作为json对象返回。 代码如下所示。 这不是生成器代码。 更改几行将使它成为一个生成器。

import json

curly_idx = []
jstr = ""
first_curly_found = False
with open("C:\\Users\\Rajeshs\\PycharmProjects\\Project1\\data\\test.json", 'r') as fp:
    #Reading file line by line
    line = fp.readline()
    lnum = 0
    while line:
        for a in line:
            if a == '{':
                curly_idx.append(lnum)
                first_curly_found = True
            elif a == '}':
                curly_idx.pop()

        # when the right curly for every left curly is found,
        # it would mean that one complete data element was read
        if len(curly_idx) == 0 and first_curly_found:
            jstr = f'{jstr}{line}'
            jstr = jstr.rstrip()
            jstr = jstr.rstrip(',')
            jstr[:-1]
            print("------------")
            if len(jstr) > 10:
                print("making json")
                j = json.loads(jstr)
            print(jstr)
            jstr = ""
            line = fp.readline()
            lnum += 1
            continue

        if first_curly_found:
            jstr = f'{jstr}{line}'

        line = fp.readline()
        lnum += 1
        if lnum > 100:
            break

您正在使用同一文件对象开始多次解析迭代而不重置它。 第一次调用 ijson 会起作用,但会将文件对象移动到文件末尾; 然后你第二次将 same.object 传递给 ijson 时它会报错,因为没有任何东西可以从文件中读取了。

每次调用 ijson 时尝试打开文件; 或者,您可以在调用 ijson 后查找文件的开头,以便文件对象可以再次读取您的文件数据。

if you are working with json with the following format you can use ijson.item()



sample json:

[
    {"id":2,"cost":0,"test":0,"testid2":255909890011279,"test_id_3":0,"meeting":"daily","video":"paused"}
    {"id":2,"cost":0,"test":0,"testid2":255909890011279,"test_id_3":0,"meeting":"daily","video":"paused"}

]





  input = 'file.txt'
        res=[]
        if Path(input).suffix[1:].lower() == 'gz':
            input_file_handle = gzip.open(input, mode='rb')
        else:
            input_file_handle = open(input, 'rb')

        for json_row in ijson.items(input_file_handle,
                                    'item'):
            res.append(json_row)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM