51Testing软件测试论坛

标题: Python处理大文件的效率问题! [打印本页]

作者: 悠悠小仙仙    时间: 2017-6-19 13:32
标题: Python处理大文件的效率问题!
最近觉得python脚本比vbs强大不少,改用python。基础处理功能顺手不少。但开始处理大文件的时候发现较为严重的效率问题。特到此求助一下。
以下未特别注明,python均采用python.org的3.5版本(应该是CPython3.5)
一、大型文件的读取效率(分享,已解决)
      面对100w行的大型数据,经过测试各种文件读取方式,得出结论:
Python code
  1. with open(filename,"rb") as f:
  2.     for fLine in f:
  3.         pass
复制代码

方式最快,100w行全遍历2.7秒。基本满足中大型文件处理效率需求。如果rb改为r,慢6倍。
但是此方式处理文件,fLine为bytes类型。但是python自行断行,仍旧能很好的以行为单位处理读取内容。

二、文本处理效率问题(100分求助)
       由于我处理的是ascii定长文件,不是分隔符文件,故采用列表操作实现数据分割。本来没在意,结果处理20w条
数据,时间急剧上升到12s。本以为是byte.decode增加了时间。遂去除decode全程bytes处理。发觉仍旧效率堪忧。
最后用最简单方式测试,首次运行,最简单方式也要7.5秒100w次。
Python code
  1. #打开文件
  2. import time;

  3. tbs="000000001111000002222222233333333000000004444444QAZ55555555000000006666666ABC这些事中文字                                                                                                                                                                                                                                                                                           "

  4. tb=tbs.encode("GBK")
  5. tl=(11,10,2,11,14,5,5,14,3,80,200,15)
  6. trs=[]
  7. def BFFPList(FWidth,PrsrStr):
  8.     # 判断是否为bytes
  9.     if isinstance(PrsrStr, str):
  10.         tbytes=PrsrStr.encode("GBK")
  11.     else:
  12.         tbytes=PrsrStr

  13.     ffpvalues=[]
  14.     j=0
  15.     x=len(FWidth)
  16.     for i in range(x):
  17.         # try:           
  18.             ffpvalues.append(tbytes[j:j+FWidth[i]])
  19.             
  20.         # except BaseException as arg:
  21.         #     print("e=",arg,"i=",i,"PrsrStr=",PrsrStr)
  22.          
  23.             j+=FWidth[i]
  24.     return ffpvalues

  25. def test(arg1):
  26.     ticks=time.clock()
  27.     for x in range(arg1):
  28.         trs=BFFPList(tl,tb)
  29.     print("test共计有%d次,耗时%16.6f秒"%(l,time.clock()-ticks))
  30.     print("结果=",trs)

  31. a="abcdefghijklabcdefghijkl"
  32. ab=a.encode("GBK")
  33. aw=(2,2,2,2,2,2,2,2,2,2,2,2)
  34. def test1(arg1):
  35.     ticks=time.clock()
  36.     for x in range(arg1):
  37.         trs=tt(aw, ab)
  38.     print("test1共计有%d次,耗时%16.6f秒"%(l,time.clock()-ticks))
  39.     print("结果=",trs)

  40. def tt(argN,argByte):
  41.     f=[]
  42.     j=0
  43.     x=len(aw)
  44.     for i in range(x):
  45.         t=j+aw[i]
  46.         f.append(argByte[j:t])
  47.         j,t=t,j
  48.     return f

  49. l=1000000

  50. test(l)
  51. test1(l)
复制代码
用vb6采用全byte数组操作,100w次仅仅1秒。python连vb6的效率都不如?以下为vb6处理代码。

Visual Basic code
  1. Dim ab() As Byte
  2.     ab = StrConv("abcdefghijklabcdefghijkl", vbFromUnicode)
  3.     Dim i As Long
  4.     Dim aw() As Long
  5.     ReDim aw(11)
  6.     For i = 0 To 11
  7.         aw(i) = 2
  8.     Next i
  9.     Dim ss As Date
  10.     ss = Now
  11.     Dim rr() As Byte
  12.     For i = 0 To 1000000
  13.         rr = tt(aw, ab)
  14.     Next i
  15.     MsgBox "time=" & DateDiff("s", ss, Now)
复制代码
由于对python3.5还是不太精通,想求助一下大家,是否还有优化性能的可能性。BFFPList函数,执行效率是否还能提升一个数量级?

附加求助:tkinter界面出现大规模io操作,会卡死。由于无类似vb6的doevents函数。即使牺牲效率换界面也不可行。
可以在间歇期间用 .update更新内容。不过 ttk.Progressbar 碰到遍历文件,直接卡死。不知道各位有何好的解决方式。别说多线程。我只是要进度条动而已。另外,程序逻辑是,先遍历主文件,找到索引(生成器),然后遍历相关子文件,获取明细。


作者: 草帽路飞UU    时间: 2017-6-19 17:50
跟你一比,我只是代码小白啊。只看过2本python书

python的效率并不高,所以速度不如VB应该是很正常的。
个人认为,python的特点只有一个:容易入门
作者: 乐哈哈yoyo    时间: 2017-6-21 09:38
把数据结构改一下,比如把tl改成tl={1:[11,''],2:[10,'']....}这种格式,那只要把字符串分片的值赋给对应的字典中的列表中就行了,时间肯定有大幅度的提升。




欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/) Powered by Discuz! X3.2