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

求助,用 python 从 word 向 excel 导入文本,相同文件拆分后速度快了 10 倍

  •  
  •   Tifosi · 2016-12-29 09:06:48 +08:00 · 2959 次点击
    这是一个创建于 2665 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本人小白,学 python 一个多月,想自动化一些办公流程,所以就写了个将目录下所有 word 文件遍历,再将制定列复制到 excel 的程序。

    测试优化了一个星期,然后发现了一个以我现在的了解无法解决的问题。同样是将 1300 行传送到 excel 中,我用程序跑 13 个 100 行的文件用不到 20 秒,但如果是跑一个大文件就要用 200 秒。期初我以为是 list 太大了,改成每 100 行传送一次,而不是一个大 list ,然后运行时间没有丝毫改变。。。

    我觉得是 list 存取什么的问题?不太懂,所以求助啊~~~

    代码如下

    import os
    from openpyxl import Workbook
    from openpyxl.styles import PatternFill
    from docx import Document
    import re
    import time
    
    #excel part
    wb = Workbook()
    ws = wb.active
    fil = PatternFill(start_color='FFFF00', end_color='FFFF00',fill_type='solid')
    
    #os part
    dest_dir = input('请输入外部审校文件所在路径。\n>').replace("\\", "/")
    
    def copy(range):
        return str(t.cell(range, 2).text)
    
    def del_blank(text):
        return text != ''
    
    def clean_tag(text2):
        return re.sub('<'r'/?[a-z]{0,3}[0-9]{0,5}/?''>', '', text2)
    
    for root, dirs, files in os.walk(dest_dir):
        pass
    
    for name in files:
        t = Document(os.path.join(dest_dir, name)).tables[0]
        ws.append({'B': name})
        ws['B' + str(ws.max_row)].fill = fil
        j = list(range(len(t.rows)))
        r1 = list(map(clean_tag, filter(del_blank,map(copy, j))))
        r2 = [n for n in range(len(t.rows))]
        for row in zip(r2, r1):
            ws.append(row)
    
    wb.save(dest_dir + '/删重文件.xlsx')
    
    
    10 条回复    2016-12-30 11:31:44 +08:00
    iam36
        1
    iam36  
       2016-12-29 09:23:12 +08:00
    应该是你用的这个库: openpyxl 的文件读写性能问题
    office 的读写库很多,也有官方组件可以调用,多试两个一比对就明了了

    试好回来写个报告
    justou
        2
    justou  
       2016-12-29 09:25:48 +08:00
    这种要自己 profile 一下才知道瓶颈在哪里, 光是猜测没用
    试试 cProfile, memory_profiler, 以及 line_profiler 这类工具
    tomwen
        3
    tomwen  
       2016-12-29 09:27:30 +08:00
    >>r1 = list(map(clean_tag, filter(del_blank,map(copy, j))))

    改成
    filterd = filter(del_blank,map(copy, j))
    r1 = list(map(clean_tag, flilterd))
    试试
    Tifosi
        4
    Tifosi  
    OP
       2016-12-29 09:27:34 +08:00
    @iam36 好像不是,我分开测过时间,耗时都在
    ···
    r1 = list(map(clean_tag, filter(del_blank,map(copy, j))))
    ···
    这一句上
    Tifosi
        5
    Tifosi  
    OP
       2016-12-29 10:49:53 +08:00
    @tomwen 没有变化啊,我挨个拆开试过,虽然是一步步赋值,但 python 是一块计算的
    Tifosi
        6
    Tifosi  
    OP
       2016-12-29 10:50:34 +08:00
    @justou 我去试试,还没接触过这个
    18600491593
        7
    18600491593  
       2016-12-29 10:58:54 +08:00 via Android
    什么不用.net
    毕竟都是自家人
    tairan2006
        8
    tairan2006  
       2016-12-29 14:07:01 +08:00
    Python 处理数据最好用`Pandas`和`Numpy`,这两个是历尽考验的大数据库
    264768502
        9
    264768502  
       2016-12-30 09:55:19 +08:00
    r1 = list(map(clean_tag, filter(del_blank,map(copy, j))))
    r2 = [n for n in range(len(t.rows))]
    试试看把这个 r1 和 r2 拆成多个生成器表达式

    还有,多次用同一个正则的话,最好预编译好,再调用,不要直接用 re.sub

    通过 Profile,如果发现瓶颈在 copy(range)的话,那就要考虑换一个 docx 的解析库了,就如楼上所说
    Tifosi
        10
    Tifosi  
    OP
       2016-12-30 11:31:44 +08:00
    问题解决了,时间都消耗在从 word 取出文本放在数列了
    for cell in t.columns[2].cells:
    j.append(re.sub('<'r'/?[a-z]{0,3}[0-9]{0,5}/?''>', '', cell.text))
    改成这句之后速度提高了 20 倍
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1182 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 18:19 · PVG 02:19 · LAX 11:19 · JFK 14:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.