51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1330|回复: 2
打印 上一主题 下一主题

[原创] Python处理大文件的效率问题!

[复制链接]
  • TA的每日心情

    1720761397
  • 签到天数: 1 天

    连续签到: 1 天

    跳转到指定楼层
    1#
    发表于 2017-6-19 13:32:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    最近觉得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 碰到遍历文件,直接卡死。不知道各位有何好的解决方式。别说多线程。我只是要进度条动而已。另外,程序逻辑是,先遍历主文件,找到索引(生成器),然后遍历相关子文件,获取明细。

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    该用户从未签到

    2#
    发表于 2017-6-19 17:50:25 | 只看该作者
    跟你一比,我只是代码小白啊。只看过2本python书

    python的效率并不高,所以速度不如VB应该是很正常的。
    个人认为,python的特点只有一个:容易入门
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    无聊
    2024-7-12 13:16
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]测试小兵

    3#
    发表于 2017-6-21 09:38:07 | 只看该作者
    把数据结构改一下,比如把tl改成tl={1:[11,''],2:[10,'']....}这种格式,那只要把字符串分片的值赋给对应的字典中的列表中就行了,时间肯定有大幅度的提升。
    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-14 14:21 , Processed in 0.065401 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表