7

我见过很多与此类似的问题,但没有一个真正匹配的问题。大多数其他问题似乎与速度有关。我遇到的是一个 json 字典,它位于我本地机器上的一个 1.1gig 文件中,当我尝试使用以下任何内容加载它时,它占用了我所有的 16 GB 内存:

f = open(some_file, "rb")
new_dictionary = json.load(f)

无论我使用什么 json 库(我尝试过 ujson、json、yajl),无论我是否将内容作为字节流读取,都会发生这种情况。这对我来说完全没有意义。疯狂的内存使用是怎么回事,我该如何解决?

如果有帮助,字典只是一堆嵌套字典,它们都具有指向其他整数的整数。示例如下所示:

{"0":{"3":82,"4":503,"15":456},"956":{"56":823,"678":50673,"35":1232}...}

更新:当我使用 simplejson 运行它时,它实际上只占用了 8 个演出。不知道为什么那个比其他所有占用的要少得多。

更新2:所以我做了更多调查。我用 simplejson 加载了我的字典,并尝试将所有键转换为整数(根据 Liori 的建议,字符串可能会占用更多空间)。空间在 8 场演出时保持不变。然后我尝试了 Winston Ewert 关于运行 gc.collect() 的建议。空间仍然保持在 8 场演出。最后,又恼又好奇,我腌制了我的新数据结构,退出了 Python,然后重新加载。瞧,它仍然需要 8 个演出。我猜 Python 只是想要这么大的空间来存放一个大的 2d 字典。当然令人沮丧,但至少现在我知道这不是 JSON 问题,只要我使用 simplejson 加载它。

4

4 回答 4

3

You could try with a streaming API:

http://lloyd.github.com/yajl/

of which there are a couple of python wrappers.

https://github.com/rtyler/py-yajl/

https://github.com/pykler/yajl-py

于 2012-05-05T09:49:30.517 回答
2

我的一个小实验表明,gc.collect()在解析 json 对象后调用会将内存使用量降低到最初构造对象时的位置。

这是我在较小范围内获得的内存使用结果:

Build. No GC
762912
Build. GC
763000
Standard Json. Unicode Keys. No GC
885216
Standard Json. Unicode Keys. GC
744552
Standard Json. Int Keys. No GC
885216
Standard Json. Int Keys. GC
744724
Simple Json. Unicode Keys. No GC
894352
Simple Json. Unicode Keys. GC
745520
Simple Json. Int Keys. No GC
894352
Simple Json. Int Keys. GC
744884

基本上,运行 gc.collect() 似乎可以清除 JSON 解析过程中产生的某种垃圾。

于 2012-05-05T00:55:10.230 回答
0

我不敢相信我要说这个,但 json 实际上是一种非常简单的格式,构建自己的解析器不会太难。

也就是说,只有在以下情况下才有意义:

  • 最后您不需要完整的字典(即,您可以在阅读时使用数据)
  • 您很清楚数据的结构类型(任意深度的字典会使这变得更加困难)
于 2012-05-05T00:01:58.363 回答
0

Gabe 确实在评论中发现了这一点,但由于已经几个月了,他还没有将其发布为答案,我想我应该回答我自己的问题,所以后人看到有答案。

无论如何,答案是 2d 字典在 Python 中只占用了这么多空间。这些字典中的每一个最终都会有一些空间开销,并且由于它们很多,它会从 1.1 gig 激增到 8 gig,除了尝试使用不同的数据结构或获得更多数据之外,您无能为力内存。

于 2012-08-23T18:25:03.970 回答