从大型json文件加载python元素
这是我的json文件。我想从中逐个加载数据列表,并且只加载它。然后,举例来说,绘制它 这是一个例子,因为我处理的是大数据集,无法加载所有文件(这将导致内存错误) 以下是我尝试过的: 它不返回任何内容,即使我尝试将其转换为列表:从大型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的结构,我会这样做:
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解决了这个问题,它可以正常工作。以下是执行此操作的主要步骤:
这对我很有用。我不再有这种“内存错误”问题。我没有使用我使用的代码,因为我认为这不是一种好的方法。。。导入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