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

一个读取和分析大文件的 python script 的优化问题

  •  
  •   airbob ·
    airbob · 2014-02-27 16:53:36 +08:00 · 8279 次点击
    这是一个创建于 3921 天前的主题,其中的信息可能已经有所发展或是发生改变。
    老板要写一个script 来分析几个文档,一个文档大约28,000,000 行(文件大小700M - 1G左右),有六个类似文档。
    要求就是把里面同一个user id, 同一月里是同一hour,同一个weekday的数据加和,然后写出文档。
    比如5.1号2点和5.8号2点的数据要加起来,如果时间段没相关数据,则为0
    (文档里数据为2012年5月到12月)

    script 写好了,在小文件上试验都可以跑而且结果是对的,现在问题是用在大文档上面了,已经跑了20个小时左右了,才跑了十分之一左右,若照现在的进度,这个script 跑完应该要花四五天。

    我怀疑的瓶颈大约有两个一个有可能在文件读写IO,另一个可能是我的for loop (遍历5-12月,monday - sunday, 00点到23点)里花了太长时间process, 目前我还没想到可以优化的方法。


    文件格式和现在的现在script都放在gist 里了,哪位大神给看看?



    谢谢!
    15 条回复    1970-01-01 08:00:00 +08:00
    wangfengmadking
        1
    wangfengmadking  
       2014-02-27 17:11:55 +08:00
    这种大文件,最好用

    with open("file_name", 'r') as input:
    for line in input:
    #process
    JerryKwan
        2
    JerryKwan  
       2014-02-27 17:14:42 +08:00
    @airbob
    对于大文件最好不要使用readlines
    exch4nge
        3
    exch4nge  
       2014-02-27 17:19:35 +08:00
    疑问:每个用户即使在某个时间段没有记录也需要去输出Log吗?

    你那个循环总共循环 月数 * 7 * 24 * 这个User的记录数。肯定会慢吧。。。
    你应该按照User的记录进行循环,分析每条记录,分析出是哪月星期几几时,然后原值上加上这条记录的值。
    airbob
        4
    airbob  
    OP
       2014-02-27 17:28:16 +08:00
    @wangfengmadking @JerryKwan 好的, 我试下with open("file_name", 'r') as input: 然后计算下时间
    airbob
        5
    airbob  
    OP
       2014-02-27 17:34:11 +08:00
    @exch4nge 嗯,要求是没记录也log,这样每个user有相同数目的data point.

    你说的很对,good point! 确实没有必要3个for loop, 可以直接定义个起始都为0 的2D array ( 3 x 8*7*24 ) 来存记录,这样遍历一遍有符合的相加就可以了。

    非常感谢!
    family
        6
    family  
       2014-02-27 17:37:33 +08:00
    先把文件拆分为方便计算的子文件,可以按照时间一共拆分24个文件,然后统计。
    exch4nge
        7
    exch4nge  
       2014-02-27 17:53:35 +08:00
    @airbob 提个建议啊

    - python支持 a, b = ['a', 'b'] 这类的赋值。
    - 可以开辟array来记录,但中间你需要做字符串--数字的映射关系。如果用dict来记录的话,可以省很多事。
    - python中的字符串是不可变的,所以每次outputCONTENT = outputCONTENT + contents[0] 好像会增加内存使用量的。你这例子还好,内存够用,如果再大点,就得注意内存问题了。
    airbob
        8
    airbob  
    OP
       2014-02-27 20:25:03 +08:00
    @exch4nge @family 谢谢大家,改好了,现在跑一遍10-20分钟,6个文档已经跑完了,week-modified.py更新了放在gist 上了~
    likuku
        9
    likuku  
       2014-02-28 00:53:25 +08:00
    嗯,dict 或者 dict 的嵌套 作状态记录很方便,查询更新也方便。
    lixm
        10
    lixm  
       2014-02-28 09:46:36 +08:00
    导入mysql,直接sql查询
    oio
        11
    oio  
       2014-02-28 10:16:01 +08:00
    我也来试试看....不适用于乱序数据....

    <script src="https://gist.github.com/onia/9263792.js"></script>
    exch4nge
        12
    exch4nge  
       2014-02-28 16:14:22 +08:00
    @oio 学习了csv, groupby等炫酷的玩意
    anguskwan
        13
    anguskwan  
       2014-02-28 17:10:24 +08:00
    导入mysql ^ ^
    oio
        14
    oio  
       2014-03-01 14:33:56 +08:00
    @exch4nge, 我总觉得满足 PEP8 每行 <79 很难,怎么破....
    exch4nge
        15
    exch4nge  
       2014-03-01 22:57:19 +08:00
    @oio 2格缩进 + 合理的换行?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3574 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 46ms · UTC 10:23 · PVG 18:23 · LAX 02:23 · JFK 05:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.