有一个很大的 json 文件,要如何才能将它读到内存中呢, 4 个多 G - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
RicardoScofileld
V2EX    Python

有一个很大的 json 文件,要如何才能将它读到内存中呢, 4 个多 G

  •  1
     
  •   RicardoScofileld 2018-06-05 11:40:12 +08:00 15863 次点击
    这是一个创建于 2714 天前的主题,其中的信息可能已经有所发展或是发生改变。

    尝试用 pickle.loads 读到内存,直接内存溢出了,试着用 pandas.read_json()读取,但是报错,Excepted object or value 黔驴技穷,不知道该咋弄了

    第 1 条附言    2018-06-05 15:42:51 +08:00
    可能我的描述出了点问题,该对象是用 pickle.dump 出去的,然后再 load 进来的时候,会内存溢出。。。。。
    60 条回复    2018-06-14 17:14:36 +08:00
    opengps
        1
    opengps  
       2018-06-05 11:45:46 +08:00
    要不你试试用工具把内存映射成硬盘,然后当作硬盘读写?
    不过貌似没有长期免费的内存映射硬盘工具
    purebluesong
        2
    purebluesong  
       2018-06-05 12:17:48 +08:00
    怎么写的怎么读吧,python 的 loads 会在内存中占用成 10 倍磁盘空间的大小。
    不过如果 Expected object or value 的话应该这个文件本身就有问题了,说不定因为文件大小限制而被截断了
    Luckyray
        3
    Luckyray  
       2018-06-05 12:18:41 +08:00 via iPhone
    这么大还用 json 不太合适吧……
    likuku
        4
    likuku  
       2018-06-05 12:20:27 +08:00
    某些数据库已经支持 Json 数据类型了,先塞进去,Py 再去读 DB 呢?
    zynlp
        5
    zynlp  
       2018-06-05 12:20:48 +08:00 via iPhone   1
    加内存,就是这么直接
    janxin
        6
    janxin  
       2018-06-05 12:21:33 +08:00
    才 4 个 G 不会爆内存的吧...你内存不够了?
    ho121
        7
    ho121  
       2018-06-05 12:25:21 +08:00 via Android   1
    自己写个 json 解释器,支持流式读取
    twor2
        8
    twor2  
       2018-06-05 12:25:23 +08:00 via iPhone
    开一个临时的大内存云服务器
    lesteryu
        9
    lesteryu  
       2018-06-05 12:31:19 +08:00   1
    pip install ijson
    Bramblex2
        10
    Bramblex2  
       2018-06-05 12:38:59 +08:00 via iPhone
    你这 json 什么结构啊…如果层数深还是长度长?
    maxco292
        11
    maxco292  
    &nsp;  2018-06-05 13:11:53 +08:00
    iwtbauh
        12
    iwtbauh  
       2018-06-05 13:36:02 +08:00 via Android   1
    @opengps Linux 自带 mount -t tmpfs 了解一下,内存文件系统,比内存盘还要高效
    shilyx
        13
    shilyx  
       2018-06-05 13:36:52 +08:00
    将你的需求映射为数据接口由 c++来处理,C++用 rapidjson 来读取

    rapidjson 如果还是不行,就用 c++写一个针对文件的、有限功能的 json 库

    如果自己搞不定,就外包
    iwtbauh
        14
    iwtbauh  
       2018-06-05 13:37:34 +08:00 via Android
    使用 64 位处理器,64 位操作系统和 64 位 Python 尝试

    从理论上讲,64 位进程的虚拟内存可以高达 EB 级别( 32 位进程的虚拟内存通常只有 2GB 或 3GB,不可能超过 4GB )
    scriptB0y
        15
    scriptB0y  
       2018-06-05 13:41:56 +08:00
    建议使用 less 这种文本阅读工具看一下内容,然后根据内容用代码一部分一部分的读然后切成小文件,应该是比较快的方法。
    lihongjie0209
        16
    lihongjie0209  
       2018-06-05 13:57:00 +08:00
    为什么不先导入到数据库
    graysheeep
        17
    graysheeep  
       2018-06-05 14:05:39 +08:00
    搞策略交易么
    est
        18
    est  
       2018-06-05 14:07:16 +08:00
    #9 楼 @lesteryu 回复正解。迭代式解析 json 即可。内存绝对不会爆炸。
    RicardoScofileld
        19
    RicardoScofileld  
    OP
       2018-06-05 14:23:07 +08:00
    @opengps 没接触过这种工具,推荐一个谢谢啦
    RicardoScofileld
        20
    RicardoScofileld  
    OP
       2018-06-05 14:24:38 +08:00
    @purebluesong 你说为啥 load 的时候,会达到文件本身 10 倍的内存占用呢,是因为 Python 的数据类型导致的吗
    RicardoScofileld
        21
    RicardoScofileld  
    OP
       2018-06-05 14:25:39 +08:00
    @Luckyray 哎,我老大写的代码,要我优化,他服务器 32 个 G 的内存,给我开了一个 8G 的,我跑代码特么的动不动就内存溢出。真的头大
    RicardoScofileld
        22
    RicardoScofileld  
    OP
       2018-06-05 14:26:17 +08:00
    @zynlp 真粗暴,有没有什么免费的骚操作
    RicardoScofileld
        23
    RicardoScofileld  
    OP
       2018-06-05 14:27:01 +08:00
    @janxin 文件大小虽然是 4 个 G,但是 load 的时候会造成很多倍的内存占用,也不知道为什么
    RicardoScofileld
        24
    RicardoScofileld  
    OP
       2018-06-05 14:27:44 +08:00
    @ho121 大佬,可以来个示范代码或者链接吗,万分感激
    RicardoScofileld
        25
    RicardoScofileld  
    OP
       2018-06-05 14:28:48 +08:00
    @twor2 公司 32G 的服务器,也会跑崩
    RicardoScofileld
        26
    RicardoScofileld  
    OP
       2018-06-05 14:29:18 +08:00
    @lesteryu 查阅相关资料的时候看到这个库,我去了解一下
    RicardoScofileld
        27
    RicardoScofileld  
    OP
       2018-06-05 14:29:34 +08:00
    @Bramblex2 字典,嵌套字典
    RicardoScofileld
        28
    RicardoScofileld  
    OP
       2018-06-05 14:31:32 +08:00
    @lihongjie0209 这算一个临时的中间文件,所以没有保存数据库
    RicardoScofileld
        29
    RicardoScofileld  
    OP
       2018-06-05 14:36:18 +08:00
    @iwtbauh Python 版本倒是 64 位的其他就不知道了
    RicardoScofileld
        30
    RicardoScofileld  
    OP
       2018-06-05 14:38:53 +08:00
    @shilyx 小弟的水平看来只能 GG 了
    linuxchild
        31
    linuxchild  
       2018-06-05 14:54:26 +08:00
    单机 spark 试试?
    USNaWen
        32
    USNaWen  
       2018-06-05 14:59:48 +08:00
    rapidjson,用 SAX+流式。
    https://github.com/Tencent/rapidjson
    ipeony
        33
    ipeony  
       2018-06-05 15:13:26 +08:00
    导 mongodb 里
    flyingghost
        34
    flyingghost  
       2018-06-05 15:47:43 +08:00   4
    首先,先搞清楚你把数据加载到内存后打算干吗。
    这坨数据就是比你内存大,和格式无关。哪怕它是再精简不过的 bin 格式,哪怕我用 c,都无法解决 8G 内存读取 800G 数据的矛盾。
    唯一的出路,就是根据数据格式和需求确定解析和计算模式,部分解析,部分计算,分治然后汇总。

    建议的几种读取方式:
    1,SAX 了解一下,事件流驱动的 xml 解析思路,搬到 json 上毫无问题。
    2,切割原 json 文件,给它补上恰当的开始、关闭符来确保结构。
    3,自己实现解析器,最 low 的状态机实现起来很简单的。然后一边解析一边处理一边丢弃。
    4,如果 json 数据有某种特征,预处理一下。(比如结构体其实不复杂元素也不多,但里面有个字段的值超大,那么先文本处理 json,把这个字段抽取出来形成外部文件,json 内只留个文件名索引)其实很多超大数据集要么结构简单只是数据条数多,要么条数不多但单条比较大,很容易做针对性处理。
    yedashuai
        35
    yedashuai  
       2018-06-05 15:49:46 +08:00
    这是使用 generator 的最佳场景呀,流式读取和解析~~~
    RicardoScofileld
        36
    RicardoScofileld  
    OP
       2018-06-05 15:56:51 +08:00
    @flyingghost 这个本来是很多个文件处理后生成的一个字典,然后用 pickle dump 出去,生成一个临时中间文件,避免下次使用的时候还要经过计算生成,但是在 load 的时候,不知道为什么内存占用会成倍的增长。
    RicardoScofileld
        37
    RicardoScofileld  
    OP
       2018-06-05 15:57:26 +08:00
    @yedashuai 用 pickle 生成的文件,要如何流式读取解析呢
    henglinli
        38
    henglinli  
       2018-06-05 16:28:49 +08:00 via iPhone
    这就是典型设计问题啊
    jyf
        39
    jyf  
       2018-06-05 16:39:07 +08:00
    有流式解析的 不过这要看你的数据本身的结构 34 楼已经说得很清楚了
    RedFlag2233
        40
    RedFlag2233  
       2018-06-05 16:48:49 +08:00 via Android
    with as
    crist
        41
    crist  
       2018-06-05 17:00:32 +08:00
    请装 16G 的内存,谢谢。
    focusheart
        42
    focusheart  
       2018-06-05 18:05:51 +08:00
    嗯,看了补充内容,标题有歧义。
    标题的一般理解是有个 4G 多的 xxx.json 的纯文本文件。
    而实际上是一个 pickle dump 出来的对象文件比如 xxx.pkl 。
    显然用 pd.read_json() 是无法读取这个 xxx.pkl 的,也不用考虑流式之类的问题。

    这样几种方法解决:
    1. 如#41 所说,加内存,简单有效省事。
    2. 用 json 的话,重新用 json.dump() 搞一个纯文本的 xxx.json。纯文本怎么都好办。
    3. pickle 并不适合搞大对象的保存。换个库来做对象序列化,marsahl 好一些,但是要注意 python 版本。
    diggerdu
        43
    diggerdu  
       2018-06-05 18:54:34 +08:00
    临时加个 swapfile
    aimiyooo
        44
    aimiyooo  
       2018-06-05 23:28:00 +08:00
    4 个 G 数据,加载到内存可远远不止 4G
    exhades
        45
    exhades  
       2018-06-06 00:03:25 +08:00
    加内存咯....不过全部加载到内存干什么.....
    qwertyegg
        46
    qwertyegg  
       2018-06-06 01:17:41 +08:00
    NoSQL
    feiffy
        47
    feiffy  
       2018-06-06 09:07:45 +08:00
    如果都是条数多,嵌套层数少,相同元素多,可以流式读取文件,generator 处理啊
    RicardoScofileld
        48
    RicardoScofileld  
    OP
       2018-06-06 09:24:16 +08:00
    @jyf 额 是我的描述出了点问题,pickle.dump 是异于 json.dump 的,是一个超大的字典,dump 出去有 4 个多 G,但是 load 的时候内存占用成倍的增长,直接溢出
    RicardoScofileld
        49
    RicardoScofileld  
    OP
       2018-06-06 09:25:14 +08:00
    @crist 文件达到将近 5 个 G 的时候,32G 内存服务器偶尔会崩。。。。
    RicardoScofileld
        50
    RicardoScofileld  
    OP
       2018-06-06 09:26:58 +08:00
    @focusheart 是啊,我原以为这两个库作用是相同的,查阅资料的时候才发现是有区别的,误导了大家了,尴尬
    RicardoScofileld
        51
    RicardoScofileld  
    OP
       2018-06-06 09:27:23 +08:00
    @diggerdu 谢谢,我去了解一下
    RicardoScofileld
        52
    RicardoScofileld  
    OP
       2018-06-06 09:29:17 +08:00
    @aimiyooo 是啊,pickle dump 出去只有 4 个 G,load 进来的时候却成倍的增长,是不是因为数据结构的原因呢
    RicardoScofileld
        53
    RicardoScofileld  
    OP
       2018-06-06 09:31:28 +08:00
    @exhades 是经过处理计算的一个字典,为了减少下次运算时间,所以打算用空间换取时间,dump 出一个中间临时文件,到时候直接 load 进来的
    RicardoScofileld
        54
    RicardoScofileld  
    OP
       2018-06-06 09:34:07 +08:00
    @qwertyegg 如果用 nosql,我想了一下,对于 redis,貌似只能用 hash 类型,但是这个字典里面有嵌套,要保存的话,还是需要序列化
    lfzyx
        55
    lfzyx  
       2018-06-06 10:16:19 +08:00
    大多数应用程序都必须检索整个对象,然后仅过滤出所需数据以进行进一步分析。借助 S3 Select,应用程序可以将过滤和访问对象内部数据的繁重工作卸载到 Amazon S3 服务。

    https://aws.amazon.com/cn/about-aws/whats-new/2018/04/amazon-s3-select-is-now-generally-available/?nc1=f_ls
    ofooo
        56
    ofooo  
       2018-06-06 11:06:13 +08:00
    你老大 32G 内存,你就和你老大说一下不就完了吗。需求不合理就提。
    liangeeks
        57
    liangeeks  
       2018-06-06 11:58:06 +08:00
    这么大,知道数据结构的话慢慢读,不用一次性 load 啊
    RicardoScofileld
        58
    RicardoScofileld  
    OP
       2018-06-06 13:53:34 +08:00
    @liangeeks pickle dump 出去的,怎么慢慢读呢
    cctv1005s927
        59
    cctv1005s927  
       2018-06-06 14:48:33 +08:00
    自己搞一个数据结构存放文件吧,json 的文件是有深度的,有些时候不读取完毕很难读取到一个 object 的内容。
    beforeuwait
        60
    beforeuwait  
       2018-06-14 17:14:36 +08:00
    用 生成器呀
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1100 人在线   最高记录 6679       Select Language
    World is powered by solitude
    VERSION: 3.9.8.5 84ms UTC 17:36 PVG 01:36 LAX 09:36 JFK 12:36
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86