从大型json文件加载python元素

从大型json文件加载python元素,python,json,python-2.7,ijson,Python,Json,Python 2.7,Ijson,这是我的json文件。我想从中逐个加载数据列表,并且只加载它。然后,举例来说,绘制它 这是一个例子,因为我处理的是大数据集,无法加载所有文件(这将导致内存错误) 以下是我尝试过的: 它不返回任何内容,即使我尝试将其转换为列表: [] 考虑到json的结构,我会这样做: import json filename = "test.json" with open(filename) as data_file: data = json.load(data_file) print data[

这是我的json文件。我想从中逐个加载数据列表,并且只加载它。然后,举例来说,绘制它

这是一个例子,因为我处理的是大数据集,无法加载所有文件(这将导致内存错误)

以下是我尝试过的:

它不返回任何内容,即使我尝试将其转换为列表:

[]

考虑到json的结构,我会这样做:

import json

filename = "test.json"

with open(filename) as data_file:
    data = json.load(data_file)
print data['earth']['europe'][2]['data']
print type(data['earth']['europe'][2]['data'])

您需要指定一个有效的前缀;ijson前缀要么是字典中的键,要么是列表项的单词
。您无法选择特定的列表项(因此
[2]
不起作用)

如果您需要
欧洲
列表中的所有
数据
键词典,则前缀为:

earth.europe.item.data
# ^ ------------------- outermost key must be 'earth'
#       ^ ------------- next key must be 'europe'
#              ^ ------ any value in the array
#                   ^   the value for the 'data' key
这将生成每个这样的列表:

>>> l = ijson.items(f, 'earth.europe.item.data')
>>> for data in l:
...     print data
...
[1, 7, 4, 7, 5, 7, 7, 6]
[1, 0, 4, 1, 5, 1, 1, 1]
[1, 0, 0, 0, 5, 0, 0, 0]
您不能在其中放入通配符,因此无法获取
earth.*.item.data

如果需要进行更复杂的前缀匹配,则必须使用
ijson.parse()
函数并处理由此产生的事件。您可以重用
ijson.ObjectBuilder()
类将感兴趣的事件转换为Python对象:

parser = ijson.parse(f)
for prefix, event, value in parser:
    if event != 'start_array':
        continue
    if prefix.startswith('earth.') and prefix.endswith('.item.data'):
        continent = prefix.split('.', 2)[1]
        builder = ijson.ObjectBuilder()
        builder.event(event, value)
        for nprefix, event, value in parser:
            if (nprefix, event) == (prefix, 'end_array'):
                break
            builder.event(event, value)
        data = builder.value
        print continent, data

这将使用
'data'
键打印列表中的每个数组(因此位于以
'.item.data'
结尾的前缀下),并使用
'earth'
键。它还提取了大陆键。

因此,我将解释我最终是如何解决这个问题的。第一个答案将起作用。但是你必须知道,用ijson一个一个地加载元素会很长。。。最后,您没有加载的文件

因此,重要的信息是窗口将每个进程的内存限制为2或4 GB,具体取决于您使用的窗口(32或64)。如果您使用pythonxy,它将是2GB(它只存在于32中)。不管怎么说,这两方面都很低

我通过在windows中安装一个虚拟Linux解决了这个问题,它可以正常工作。以下是执行此操作的主要步骤:

  • 安装
  • 安装Ubuntu
  • 在计算机上安装python for scientist
  • 在两台“计算机”之间创建一个共享文件(您可以在google上找到教程)
  • 在你的ubuntu“计算机”上执行你的代码:它应该可以工作;) 注意:不要忘记给虚拟计算机提供足够的RAM和内存


    这对我很有用。我不再有这种“内存错误”问题。

    我没有使用我使用的代码,因为我认为这不是一种好的方法。。。导入ijson为ijson filename=“myfile.json”,打开(myfile,'r')为f:voila=ijson.items(f,'earth.data.item')打印。瞧,你有更新的想法吗?我已经重新打开了。我想我会删除。。。没有人响应……不,我只想从json文件加载数据列表;不是所有的json文件。问题是我有一个500 Mo的文件,当我尝试加载所有内容时,python会返回一个“内存错误”。非常感谢!即使我必须集中一点注意力在第二部分,这是我在互联网上找到的最好的解释:)我想你已经回答了这个问题,但是有没有办法一个接一个地加载这些数据?因为,如果我想治疗他们,我必须将他们(例如)存储在一个列表中。同样的问题再次出现:“内存错误”。有什么想法吗?@Jeannedidrot:是的,在我现在使用
    print
    的地方,你可以只处理那一个列表,然后丢弃它。或者您可以将整个内容封装到一个函数中,使用
    data,data
    在迭代时让它一个接一个地生成每个
    data
    列表,如果不向列表添加更多引用,它将再次被清除。好的,它可以工作!但是很慢。。。我猜是因为文件的大小。但有一件事很奇怪:如果我想加载一个元素(例如Paris),它将非常非常慢(对于长数组)。更一般地说,即使您的解释很好,ijson似乎也不是很快…@JeanneDiderot:ijson的默认后端是纯python解析器,速度很慢。安装YAJL 2.x并使用
    import ijson.backends.yajl2\u cffi as ijson
    导入一个更快的后端。不,除非您还有一个更大的JSON文件。流式解析仍然是更好的选择。如果您愿意为此使用Linux安装虚拟机,为什么不尝试使用ijson和yajl作为后端呢?因为这种方法的最大优点是,最后您可以加载文件。通常,当您进行数据处理时,您需要修改分析的参数,如果您已经加载了文件,则速度会快得多。之后,如果文件真的太大(超过几GB),我会明确推荐您的方法。但是我的文件是“只有1-2 GB。。。我想很多人都会问这个问题。无论如何,这并不是你在这里发帖的问题的答案,这似乎与ijson图书馆的使用有关。您正在回答“如何加载大型JSON文件”的问题,这是一个可能导致实际问题的问题。:-)你显然是对的!我认为你的答案是最好的;)这显然是最完整的!谢谢,非常感谢。不仅对我来说,而且对将来可能来这里专门了解如何使用ijson的访客来说也是如此。:-)
    >>> l = ijson.items(f, 'earth.europe.item.data')
    >>> for data in l:
    ...     print data
    ...
    [1, 7, 4, 7, 5, 7, 7, 6]
    [1, 0, 4, 1, 5, 1, 1, 1]
    [1, 0, 0, 0, 5, 0, 0, 0]
    
    parser = ijson.parse(f)
    for prefix, event, value in parser:
        if event != 'start_array':
            continue
        if prefix.startswith('earth.') and prefix.endswith('.item.data'):
            continent = prefix.split('.', 2)[1]
            builder = ijson.ObjectBuilder()
            builder.event(event, value)
            for nprefix, event, value in parser:
                if (nprefix, event) == (prefix, 'end_array'):
                    break
                builder.event(event, value)
            data = builder.value
            print continent, data