首页 > 解决方案 > Python/JSON 加载的对象大小因文件大小而异

问题描述

最近,我有一个文件中的数据,users.json由于文件太大(让我感到惊讶,因为它是一个29mb文件),所以在 VsCode 中加载需要很长时间,我想借此机会玩一下 python 的内存使用情况,我将文件全部加载到内存中,它按预期工作。

虽然我有一个问题,但我更需要解释,如果它的答案太明显,请原谅我;

当我对加载的json对象进行自省时,我发现对象大小 ( 1.3mb) 远小于29.6mb我的文件系统 ( ) 上的文件大小 ( MacOS),这是怎么回事?大小上的差异实在是太大了,不容忽视。更糟糕的是,我有一个较小的文件,并且该文件返回了相似大小的结果(在磁盘上/已加载,~ 358kb),哈哈。

import json

with open('users.json') as infile:
    data = json.load(infile)
    print(f'Object Item Count: {len(data):,} items \nObject Size: {data.__sizeof__():,} bytes)

使用sys.getsizeof(data)会返回类似的东西,可能会有一些gc开销。

这将返回磁盘上文件的准确大小(29586765字节,29mb

from pathlib import Path

Path('users.json').stat().st_size

请有人向我解释发生了什么,有人会认为大小应该相似,或者我错了。

标签: pythonjsonpython-3.xoopmemory

解决方案


sys.getsizeof()不递归到对象:

仅考虑直接归因于对象的内存消耗,而不考虑它所引用的对象的内存消耗。

从您的 JSON 文件中加载的所有字符串、数字等都是上述“被引用的对象”。

为了获得更准确的结果,您可以

尽管如此,一些对象在内存中会比在磁盘上小;例如,一个很大的数,比如说,36 << 921在磁盘上是 279 字节,sys.getsizeof()在内存中固定为 148 字节。同样,一个足够智能的 JSON 解码器(其中,afaik ,内置json不是默认 JSON 解码器实际执行的操作,请参阅https://github.com/python/cpython/commit/7d6e076f6d8dd48cfd748b02dad17dbeb0b346a3)可以共享对象以重复 dict 键。


推荐阅读