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
linuxchild
V2EX  ›  Python

使用 Python 处理大文件有什么推荐的方式么?

  •  
  •   linuxchild · 2017-09-23 02:14:15 +08:00 · 8111 次点击
    这是一个创建于 2605 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大概五六个 G 的文件,目前分割成了数个小文件,使用 multiprocessing 这种处理了一下,但是效率还是太低了

    请问哪位有什么推荐的方法?

    另外,我在尝试使用 pp 这个库,不过总是提示变量未定义,实际上已经定义了,使用 multiprocessing 这种都不会提示这个错误,使用的代码如下:

    cpu_num = 8
    job_server = pp.Server(cpu_num)
    a =  []
    for f in xxxxx:
        a.append(job_server.submit(func_name, (f, )))
    for x in a:
        tmp = x()
    

    有这方面经验的朋友帮一下忙,感谢

    第 1 条附言  ·  2017-09-23 11:17:33 +08:00
    目前处理速度大概是 5-6w 行每小时,总量大概 1kw 行左右…想达到的速度是一天内处理完
    第 2 条附言  ·  2017-09-23 12:34:45 +08:00
    只读写试了一下还是挺正常的,所以推测应该是我处理过程耗时比较久。

    我做的是解密处理…有对称加密也有 RSA 加密,不知道这种有什么提升的方式么……
    第 3 条附言  ·  2017-09-23 21:22:37 +08:00
    查资料发现很多人问如何提升 Java RSA 解密的性能,有部分回复说数据量大了不适合用 RSA,性能较低,然后本身密钥长度也影响效率

    考虑到 Python 当前性能提升几倍实际上还是不能满足要求,该考虑怎样用集群来解决了……

    以上,再有遇到这个问题的朋友可以参考一下。

    另,感谢各位的回复
    第 4 条附言  ·  2017-09-29 19:38:21 +08:00
    不知道还有没有人看,最终采用了 mapreduce 都方式,用时大概 2 小时都样子。

    即 map reduce 运行 python
    46 条回复    2017-09-24 23:59:36 +08:00
    linuxchild
        1
    linuxchild  
    OP
       2017-09-23 02:28:56 +08:00
    话说为什么不能 append 了…

    再说具体一些吧,就是把文件内容读出来做一些处理然后存到另外的文件去。

    不知哪位处理过类似的需求
    runjvm
        2
    runjvm  
       2017-09-23 04:17:38 +08:00 via Android
    之前的办法大概需要多久…
    laxenade
        3
    laxenade  
       2017-09-23 04:28:57 +08:00 via Android
    pyspark 跑个本地 spark
    clino
        4
    clino  
       2017-09-23 07:36:22 +08:00 via Android
    你觉得瓶颈在哪里,搞清这个最重要
    tonghuashuai
        5
    tonghuashuai  
       2017-09-23 08:15:55 +08:00 via iPhone
    现在的效率是什么样的,你想达到的预期是什么样呢?

    这个量级的文件跑几个进程去处理不至于会太慢,再不济三楼说的上 spark 也能比较快的解决,只是不知道你要求的效率什么样的。
    FindHao
        6
    FindHao  
       2017-09-23 08:57:52 +08:00 via Android
    别用 Python,,,我去年做个实验,处理 1g 的数据,由于写的 Python 比较渣,一天只处理了几 m,花了半个多小时,写了个 c 版本,十几分钟就跑完了。。
    kokutou
        7
    kokutou  
       2017-09-23 09:05:06 +08:00 via Android
    Python 写了个导出一个游戏数据的文本,要 3 ~ 4 秒的样子,用 c 写了个,1 秒不到。。。
    pathbox
        8
    pathbox  
       2017-09-23 09:44:51 +08:00 via iPhone
    我会尝试用 go
    cdwyd
        9
    cdwyd  
       2017-09-23 11:03:44 +08:00 via Android
    @FindHao
    是你自己的锅的可能性远大于 Python
    princelai
        10
    princelai  
       2017-09-23 11:13:27 +08:00 via Android
    spark 或 dask 试试
    linuxchild
        11
    linuxchild  
    OP
       2017-09-23 11:13:36 +08:00
    @runjvm 大概不到 1kw 行的数据,现在的速度是 1h 处理 5-6w … 要求的速度是不到一天处理完
    Wicked
        12
    Wicked  
       2017-09-23 11:16:08 +08:00 via iPhone
    @FindHao 才 1G,用 JS 都不需要 1 天啊…
    linuxchild
        13
    linuxchild  
    OP
       2017-09-23 11:20:29 +08:00
    @laxenade 刚刚试了试。。妈蛋服务器上 spark 环境有问题
    sunchen
        14
    sunchen  
       2017-09-23 11:20:55 +08:00
    300 多万 html,压缩后 80G,python 多进程在 4c8t 处理器上大约跑了 2 个小时做 html 解析,因为都是小文件,机械磁盘 IO 瓶颈,后期放到 ssd 上好了很多。供参考
    laqow
        15
    laqow  
       2017-09-23 11:21:05 +08:00 via Android
    以前弄过一些组学的文件,如果是纯文本的话不要用 for..in..语句,用 readlines 读入几千行后再用 readline 处理,如果是 utf8 之类非等长的字节编码的话先按 byte 编码读入文本必要时再解析成别的,最后把文件塞到内存盘再加个多进程。如果要求不高用 bash+awk 比 python 快很多。
    linuxchild
        16
    linuxchild  
    OP
       2017-09-23 11:22:12 +08:00
    @tonghuashuai 感觉是读取后处理文件比较慢…所以尝试分成了小文件,然后发现速度也没快,囧
    hasdream
        17
    hasdream  
       2017-09-23 11:22:20 +08:00 via Android
    读取多行压缩放 redis 用多台机器消费 之前处理 mysql 审计日志 30g 大概一个小时搞定 3 台 i5 机器
    Wicked
        18
    Wicked  
       2017-09-23 11:23:12 +08:00 via iPhone
    楼主先确定瓶颈在哪里,用 C++重写也就只有 2 ~ 3 倍的提升而已。对于大文件,Windows 下可以用内存映射的方式,多线程分别映射不同区域同时处理。8 核跑满应该也能提升个 5 ~ 6 倍吧
    linuxchild
        19
    linuxchild  
    OP
       2017-09-23 11:23:13 +08:00
    @FindHao 目前用了一些 py 的库,再改 C 的话感觉时间来不及…捉急
    linuxchild
        20
    linuxchild  
    OP
       2017-09-23 11:29:52 +08:00
    @pathbox 唔,还不会写 go


    @princelai 我去搜一下


    @sunchen 这个速度很快了啊,多进程用的什么库呢


    @laqow 纯文本。读取后处理的过程用到了 py 的库……所以目前想看看使用 py 有没有什么解决办法


    @hasdream 公司服务器…我装个什么东西都得审批,周末是没什么希望了


    @Wicked 对,感觉其他语言重写可能也达不到我要求对速度。 不是 windows,跑在服务器上,后期还要搞成定时任务…所以要求肯定要一天内跑完
    sunchen
        21
    sunchen  
       2017-09-23 11:35:22 +08:00
    @linuxchild multiprocessing 啊
    Wicked
        22
    Wicked  
       2017-09-23 11:39:34 +08:00 via iPhone
    Linux 应该也有类似的机制,可以查下文档。还是建议 profile 先,先从算法本身优化,热点再用 C++写一下。如果你要干的事情确实就有这么多,那你唯一可以干的就是把 CPU 吃满,换 SSD,加机器
    laqow
        23
    laqow  
       2017-09-23 11:49:07 +08:00 via Android
    感觉 python 原生解析文本的几个函数效率很低,没压缩只有几个 G 的文件问题可能在这里,应该和多进程无关
    FindHao
        24
    FindHao  
       2017-09-23 11:50:00 +08:00 via Android
    @cdwyd 很可能,哈哈。
    gamexg
        25
    gamexg  
       2017-09-23 11:58:04 +08:00
    >>现在的速度是 1h 处理 5-6w
    6w/60/60 = 16.66666666666667

    1 秒不到 17 条?
    不知道读出来做的什么处理,所以不确定是不是出问题的地方。
    你先试试只读取+处理不写看看性能,怀疑每次写都强制 sync 了。
    billion
        26
    billion  
       2017-09-23 11:59:55 +08:00
    我有处理 40G 文本文件的经验。

    我的文本文件每一行都是一个 JSON,用 Python 读取出来,再把每一行的 JSON 转成字典并插入到 MongoDB 中。使用 Python 的 readline()一行一行读,凑够了 10000 个字典以后一次性插入 MongoDB,亲测单线程单进程 4 个小时不到就跑完了。
    aru
        27
    aru  
       2017-09-23 12:31:40 +08:00
    @linuxchild
    单线程处理一下,看一下读取 /处理 /写入分别的耗时是多少
    找到瓶颈才好优化
    scys
        28
    scys  
       2017-09-23 12:31:44 +08:00
    建议你重点在优化算法逻辑处理部分,py 读 /写文件不是关键点。
    尝试下 pypy 看能不能改善。
    linuxchild
        29
    linuxchild  
    OP
       2017-09-23 12:32:05 +08:00
    @gamexg 经你这么一说,仿佛明白了一些,做的解密处理…应该是这个原因

    去掉解密,只读写没什么问题,很快…


    @laqow 解析倒是没啥问题,只是 split 一下;问题应该在处理对过程,我做的解密处理…


    @sunchen 现在用了这个,效果不太好。 试了一下 pp 想并行一下,结果出现了题目里对错误


    @billion 这么一说更觉得是我处理过程导致的速度慢了,我做的解密处理……
    linuxchild
        30
    linuxchild  
    OP
       2017-09-23 13:00:43 +08:00
    @scys 嗯,主要是数据处理这里,我处理的是加解密,瓶颈应该是在这里… pypy 无力,在服务器上,装个软件都是运帷去搞

    在想办法提高看看怎么并行处理一下


    @aru 嗯,瓶颈应该是解密这里了…目前还没有找到好的办法

    楼上说的 dask 还有我尝试的 pp 居然都碰到了错误…… pyspark 环境也有问题,想死
    laxenade
        31
    laxenade  
       2017-09-23 13:25:06 +08:00
    假设一小时单线程能处理 6w 行,那四核(超线程在这里的用途应该不大)的服务器一天也只能跑 576w 行呢。所以你有可能需要换一个更快的库或者换一个语言(
    scys
        32
    scys  
       2017-09-23 13:28:56 +08:00
    加解密你找个有 C 的模块,快起码不是一个数量级。

    或者你说说你现在有的啥模块?
    est
        33
    est  
       2017-09-23 13:39:14 +08:00
    dask

    mmap
    linuxchild
        34
    linuxchild  
    OP
       2017-09-23 14:36:57 +08:00
    @laxenade 服务器上跑的话,如果这样算,也只能尝试多几用几个核了……


    @scys 用的 pycrypto …有什么推荐的模块么


    @est 刚刚试了一下 dask

    ```
    from dask import delayed
    #import dask.bag as db
    L = []
    for fn in en_files:
    # b = db.read_text(fn)
    a = delayed(fun_name)(fn) # Delay execution of function
    L.append(a)
    result = delayed(L)
    result.compute()
    ```
    使用这种方式处理,发现和下面这种方式处理效率相似,看了看 cpu 占用率也很相似,大概都是单核 100%左右

    ```
    #pool = ThreadPool(20)
    #pool.map(decrypt_file, encrypt_files)
    #pool.close()
    #pool.join()
    ```

    话说这是我使用方式的问题,还是什么?
    laxenade
        35
    laxenade  
       2017-09-23 14:46:17 +08:00
    @linuxchild #34 所以差不多要 8 核 16 线程才能满足呢
    linuxchild
        36
    linuxchild  
    OP
       2017-09-23 14:55:03 +08:00
    @laxenade #35

    - -。要是可以的话也想试试,先跑一下看看
    用 pp 试了一下总是提示变量未定义
    scys
        37
    scys  
       2017-09-23 15:59:38 +08:00
    scys
        38
    scys  
       2017-09-23 16:04:18 +08:00
    laqow
        39
    laqow  
       2017-09-23 16:12:43 +08:00 via Android
    可能还是在 io,for fn in en_files 这个依赖系统硬盘缓存的,如果行数多但每行字少的时候很慢,主进程一次一行的分配任务会把主进程的 cpu 耗尽,不如一次 readlines 几千行塞到各个进程里在内存里由各个进程逐行处理。而且不知道为什么 python 解析 utf8 奇慢,全英文的转成其他编码的再处理。我以前遇到是这种问题。
    numoone
        40
    numoone  
       2017-09-23 17:09:50 +08:00
    难道都没看到楼主要处理的主要是加解密吗?瓶颈绝对值这啊!加解密模块用 C 来写吧!
    likuku
        41
    likuku  
       2017-09-23 17:22:49 +08:00
    找个能支持 CPU 硬件加解密加速器的库 /加解密库试试
    jhdxr
        42
    jhdxr  
       2017-09-23 19:41:08 +08:00
    最简单的答案是换 java/c/c++

    有性能要求的 Python 永远不是第一选择
    fiht
        43
    fiht  
       2017-09-23 19:50:57 +08:00
    换 pypy 可解(应该
    linuxchild
        44
    linuxchild  
    OP
       2017-09-23 20:48:32 +08:00
    @laqow 问题应该是在加解密这里,读取存储试了一下如果没有加解密还是挺快的


    @scys 感谢,回头试一下


    @numoone 对,瓶颈是这里,很费资源,该考虑换一种方式了




    @likuku 还能这样,我赶紧搜一下


    @fiht 呜呜,服务器现在还是 py2.6 呢。。装 2.7 都得给运帷打申请


    @jhdxr 那尝试一下 java 好了。。
    afpro
        45
    afpro  
       2017-09-24 00:44:20 +08:00
    这种玩意 感觉上 Cython 或者 Pypy 效果会很不错
    linuxchild
        46
    linuxchild  
    OP
       2017-09-24 23:59:36 +08:00
    @afpro 效果应该会好一些,但是可能还是不太符合性能上的要求。

    我用 pp 库把 CPU 跑满了,最后可以跑出来,但是消耗的时间依然很久,感觉用集群处理比较合适。

    准备看看怎么搞一下
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2658 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 10:20 · PVG 18:20 · LAX 02:20 · JFK 05:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.