赞
踩
论坛求助与自行摸索相结合,基本解决python大文件解析效率问题。现将过程与结论存档,供有需要者参考。
=================前言====================
看着python很火,就跑到python怀抱蹭蹭,list,dict的普通化应用,让很多编程简便了很多。
感觉还不错,就开始着手写了个常用程序,磕磕碰碰的写完。却发现大型文件处理有严重的效率问题,只好到论坛找高手。
貌似python在csdn的论坛也不火,主要靠管理员wn0112 一直帮忙互相印证改进。折腾来折腾去,效率提升仍旧不是数量级层次。
就在快要放弃,准备用c写模块来实现基础解析功能的时候,看到网上一个用法,灵机一现,总算是解决了。
结果来之不易,多啰嗦几句,感慨感慨。各位看官休怪。
=================结论=======================
环境以下没注明的情况下,python采用python.org的3.6.1版本,机器AMD AthlonII x3 450- *, win10
在讨论过程中发现,几个简单结论,
- with open(filename,"rb") as f:
- for fLine in f:
- pass
rb方式最快,100w行全遍历2.7秒。基本能满足中大型文件处理效率需求。如果rb改为r,慢6倍。
for lineNum, fline in enumerate(f) :
如果建立索引,以便后续查找定位,不建议使用传统win编程的行号定位。最好记录偏移量来进行定位。
- import itertools
- for lineNum, fline in itertools.dropwhile(lambda x:x[0] < 1073109, enumerate(f)) :
重新定位的效率会高很多很多。
文本处理,一般分为分隔符处理,定长处理。其实就是看重python3.x系列将string固化为unicode字符串,其他使用bytes类型。不是经常处理ascII,unicode不知道这种改进是多好。这也是抛弃2.7直接学3.x的原因。分隔符有各种split函数,我就不多说了。这里说定长文件。定长有unicode定长,与ascII定长。我处理的是ascii定长方式。以MS系编程经验,全bytes处理,效率最高。所以全用bytes不转换string处理。结果效率堪忧。解析20w行数据,直接上升到12s,已经成为性能瓶颈。开始使用最简单的循环拆解解析数据,100w行解析20个域,最低只能压倒5秒。用正则压倒3.5秒【如果i7机器,貌似简单循环也能压到3秒】。效率仍旧不满意。在即将放弃,准备用c重写处理函数自制模块方式提升效率,看c与python类型转换的时候,看到个函数。终于完美解决。代码如下:
import re import time import struct a="张abcdefghijklabcdefghijk" a="000000001111000002222222233333333000000004444444QAZ55555555000000006666666ABC这些事中文字 " ab=a.encode("GBK") aw=(2,3,2,2,2,2,2,2,2,2,2,2) aw=(12,9,4,8,15,3,8,15,3,80,200,15) awf=" ".join(map(lambda x:str(x)+"s",aw)) print(awf) def tt5(argN,argByte): #struck return struct.unpack(argN, argByte) def test5(arg1): ticks=time.clock() for x in range(arg1): trs=tt5(awf, ab) print("test4共计有%d次,耗时%16.6f秒"%(arg1,time.clock()-ticks)) print("结果=",trs) test5(1000000)
struct模块一般用来通信转换为字节流之用,用在此处,100w行解析20个域,可以压在1秒【i7暂时不知道能快多少】基本满足需求。
unicode定长方式,我处理这么久很少见到。可以考虑啃啃python3.x的string模块。实在不行用正则,100w行3.5秒,也可以接受。注意:re模块,如果处理bytes,那么patterns必须是bytes。如果处理string,那么patterns必须是string
csdn的python论坛,人太少。如果python实在有问题,还是找个python人多的论坛吧。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。