刚开始学习PYTHON,感觉到这个语言真的是很好用,可以快速完成功能实现。

最近试着用它完成工作中的一个任务:Linux服务器中完成对.xml.gz文件的解析,生成.csv文件,以供SqlServer服务器导入,做进一步的数据分析。

解压后的xml文件格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<bulkPmMrDataFile>
<fileHeader fileFormatVersion="V1.0.4" reportTime="2016-02-22T21:00:00.000" ></fileHeader>
<eNB id="122941">
<measurement>
<smr>MR.LteScRSRP MR.LteScRSRQ MR.LteScTadv MR.LteSceNBRxTxTimeDiff ...</smr>
<object id="31472897" MmeUeS1apId="2417300878" MmeGroupId="1025" MmeCode="199" TimeStamp="2016-02-22T20:00:02.517">
<v>38 22 6 31 34 0 34 38400 110 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL 7 23 NIL 26 24 0 0 </v>
</object>
<object id="31472897" MmeUeS1apId="2416229278" MmeGroupId="1025" MmeCode="199" TimeStamp="2016-02-22T20:00:02.792">
<v>61 30 5 32 45 0 27 38400 110 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL 7 14 NIL 1 49 0 0 </v>
</object>
<object id="31472897" MmeUeS1apId="2148286566" MmeGroupId="1025" MmeCode="199" TimeStamp="2016-02-22T20:00:07.177">
<v>42 26 5 31 30 412 35 38400 110 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL 7 14 NIL 26 24 0 0 </v>
</object>
<object id="31472897" MmeUeS1apId="2417300878" MmeGroupId="1025" MmeCode="199" TimeStamp="2016-02-22T20:00:07.677">
<v>39 22 7 31 35 387 36 38400 110 36 18 38400 108 NIL NIL NIL NIL NIL NIL NIL 5 10 NIL 25 25 0 0 </v>
</object>
<object id="31472897" MmeUeS1apId="2416229278" MmeGroupId="1025" MmeCode="199" TimeStamp="2016-02-22T20:00:07.962">
<v>61 27 5 31 43 427 36 38400 110 49 4 38400 108 NIL NIL NIL NIL NIL NIL NIL 9 13 NIL 1 49 0 0 </v>
<v>61 27 5 31 43 427 36 38400 110 46 0 38400 295 NIL NIL NIL NIL NIL NIL NIL 9 13 NIL 1 49 0 0 </v>
</object>
<object id="31472897" MmeUeS1apId="269973066" MmeGroupId="1025" MmeCode="199" TimeStamp="2016-02-22T20:00:08.382">
<v>41 23 9 32 23 447 36 38400 110 32 11 38400 358 NIL NIL NIL NIL NIL NIL NIL 6 22 NIL 24 26 0 0 </v>
<v>41 23 9 32 23 447 36 38400 110 31 7 38400 295 NIL NIL NIL NIL NIL NIL NIL 6 22 NIL 24 26 0 0 </v>
<v>41 23 9 32 23 447 36 38400 110 28 8 38400 460 NIL NIL NIL NIL NIL NIL NIL 6 22 NIL 24 26 0 0 </v>
</object>
</measurement>
<measurement>
<smr>MR.LteScPlrULQci1 MR.LteScPlrULQci2 MR.LteScPlrULQci3 MR.LteScPlrULQci4 ...</smr>
<object id="60057088" MmeUeS1apId="2416982066" MmeGroupId="1025" MmeCode="206" TimeStamp="2016-02-24T06:00:03.962">
<v>NIL NIL NIL NIL NIL NIL NIL NIL 0 NIL NIL NIL NIL NIL NIL NIL NIL 0 </v>
</object>
..........................
</measurement>
<measurement>
<smr>MR.LteScRIP</smr>
<object id="60057089:37900:2" TimeStamp="2016-02-24T06:00:11.259" MmeCode="NIL" MmeGroupId="NIL" MmeUeS1apId="NIL">
<v>81</v>
</object>
..........................
</measurement>
</eNB>
</bulkPmMrDataFile>

廖雪峰博客学习得知目前常用的两种xml解析方式为DOM和SAX,分别进行了尝试,从个人角度来看,还是DOM比较好用,包括应用逻辑以及代码编写,都相对轻松简单。

在尝试SAX解析的过程中,开始按照习惯的方式,对XML文件中筛选的可用字段进行字符串相加,导致的后果是程序运行特别的慢,于是又尝试了cStringIO内存文件,这才感受到了内存文件的速度优势。

下面列出其中的关键字段以作对比。

  • 使用字符串相加方式(s为定义的字符串变量):
#处理开始标签
def start_element(self, name, attrs):
global d_eNB
global d_obj
global s
if name == 'eNB':
d_eNB = attrs
elif name == 'object':
d_obj = attrs
elif name == 'v':
s = s + d_eNB['id']+' '+ d_obj['id']+' '+d_obj['MmeUeS1apId']+' '+d_obj['MmeGroupId']+' '+d_obj['MmeCode']+' '+d_obj['TimeStamp']+' '
else:
pass
  • 使用cStringIO内存文件方式(output为定义的cStringIO变量):
#处理开始标签
def start_element(self, name, attrs):
global d_eNB
global d_obj
if name == 'eNB':
d_eNB = attrs
elif name == 'object':
d_obj = attrs
elif name == 'v':
output.write(d_eNB['id']+' '+ d_obj['id']+' '+d_obj['MmeUeS1apId']+' '+d_obj['MmeGroupId']+' '+d_obj['MmeCode']+' '+d_obj['TimeStamp']+' ')
else:
pass

对于一个相同的.xml.gz文件,文件总行数为173890行,其中有用数据为90079行。实测结果如下:

可以看到,在应用了内存文件后,程序的处理性能有了翻天覆地的变化,处理耗时为前者的将近千分之一,赞!!!

最近又尝试修改字符串连接为list-join方式,代码如下:

  • 使用list-join方式(lst为定义的list变量):
#处理开始标签
def start_element(self, name, attrs):
global d_eNB
global d_obj
global lst
if name == 'eNB':
d_eNB = attrs
elif name == 'object':
d_obj = attrs
elif name == 'v':
lst.append(d_eNB['id']+' ')
lst.append(d_obj['id']+' ')
lst.append(d_obj['MmeUeS1apId']+' ')
lst.append(d_obj['MmeGroupId']+' ')
lst.append(d_obj['MmeCode']+' ')
lst.append(d_obj['TimeStamp']+' ')
#列表连接
t.writelines(''.join(lst).replace(' \n','\r\n').replace(' ',',').replace('T',' ').replace('NIL','')) #写入解析后内容

对于一个相同的.xml.gz文件,文件总行数为173890行,其中有用数据为90079行。实测结果如下:

可以看到,在应用了list-join方式后,处理用时和StringIO方式相当,说明利用list-join方式也能够带来和StringIO相同的性能提升。

因此,推荐在编程中要避免使用过多的字符串相加,而要以list-join和StringIO代替之。

至于为什么字符串相加效率要比其他两种低那么多呢,其实我也不是很懂,但是我会搜索啊。。。

谁说python字符串相加效率低

这个看情况分析,官方文档当中也有说,相加产生的str是immutable的,如果只是两个字符串相加,并没有什么问题,但是如果是n>>1个字符串相加,这样中间会产生n-1个中间值,这些中间值都是immutable的,所以之后就是创建一个释放一个再创建下一个释放下一个。
而join在对于n个字符串相加过程中内部实现直接全部相连,就没有这种中间值了。

如果你相加的字符串不多,用加号还是更加方便的,另一方面,你选择了用Python,还真的在乎那一两秒的效率吗?

测试用的程序和文件可以到我的github页面下载,欢迎小伙伴们一起学习讨论。

xml_parser_str.py、xml_parser_list.py、xml_parser_StringIO.py

测试用例:../mro

在PYTHON中使用StringIO的性能提升实测(更新list-join对比)的更多相关文章

  1. python中的StringIO模块

    python中的StringIO模块 标签:python StringIO 此模块主要用于在内存缓冲区中读写数据.模块是用类编写的,只有一个StringIO类,所以它的可用方法都在类中.此类中的大部分 ...

  2. Python中字符串操作函数string.split('str1')和string.join(ls)

    Python中的字符串操作函数split 和 join能够实现字符串和列表之间的简单转换, 使用 .split()可以将字符串中特定部分以多个字符的形式,存储成列表 def split(self, * ...

  3. .NET 7 中 LINQ 的疯狂性能提升

    LINQ 是 Language INtegrated Query 单词的首字母缩写,翻译过来是语言集成查询.它为查询跨各种数据源和格式的数据提供了一致的模型,所以叫集成查询.由于这种查询并没有制造新的 ...

  4. 转载:python中的StringIO模块

    注意:python3中应使用io.StringIO StringIO经常被用来作为字符串的缓存,应为StringIO有个好处,他的有些接口和文件操作是一致的,也就是说用同样的代码,可以同时当成文件操作 ...

  5. python中日志logging模块的性能及多进程详解

    python中日志logging模块的性能及多进程详解 使用Python来写后台任务时,时常需要使用输出日志来记录程序运行的状态,并在发生错误时将错误的详细信息保存下来,以别调试和分析.Python的 ...

  6. 禁用 Python GC,Instagram 性能提升10%

    通过关闭 Python 垃圾收集(GC)机制,该机制通过收集和释放未使用的数据来回收内存,Instagram 的运行效率提高了 10 %.是的,你没听错!通过禁用 GC,我们可以减少内存占用并提高 C ...

  7. API设计中性能提升的10种解决方法

    api的设计涉及到的方面很多, 分类是一个基本的思考方式.如果可以形成一个系列性的文字,那就从性能开始吧. 就像任何性能一样,API 性能主要取决于如何响应不同类型的请求.例如:典型的电商场景,显示用 ...

  8. Python性能提升小技巧

    第一部分 1-使用内建函数: 你可以用Python写出高效的代码,但很难击败内建函数. 经查证. 他们非常快速 2-使用 join() 连接字符串. 你可以使用 + 来连接字符串. 但由于string ...

  9. async/await 的基本实现和 .NET Core 2.1 中相关性能提升

    前言 这篇文章的开头,笔者想多说两句,不过也是为了以后再也不多嘴这样的话. 在日常工作中,笔者接触得最多的开发工作仍然是在 .NET Core 平台上,当然因为团队领导的开放性和团队风格的多样性(这和 ...

随机推荐

  1. Manifesto – HTML5 离线应用程序缓存校验工具

    Manifesto 是一个 HTML5 离线应用程序缓存校验工具,提供了快速校验 HTML5 manifest 文件有效性的方法.离线应用程序缓存在使用中最困难的部分之一就是无法正常工作的时候没有明显 ...

  2. 简直要逆天!超炫的 HTML5 粒子效果进度条

    我喜欢粒子效果作品,特别是那些能够应用于实际的,例如这个由 Jack Rugile 基于 HTML5 Cavnas 编写的进度条效果.看着这么炫的 Loading 效果,即使让我多等一会也无妨:)你呢 ...

  3. iOS 获取ssid

    - (NSString *)fetchSSIDInfo { NSString *ssid = nil; NSArray *ifs = (__bridge_transfer id)CNCopySuppo ...

  4. Android 抽屉效果的导航菜单实现

    Android 抽屉效果的导航菜单实现 抽屉效果的导航菜单 看了很多应用,觉得这种侧滑的抽屉效果的菜单很好. 不用切换到另一个页面,也不用去按菜单的硬件按钮,直接在界面上一个按钮点击,菜单就滑出来,而 ...

  5. Android App监听软键盘按键的三种方式与改变软键盘右下角确定键样式

    actionNone : 回车键,按下后光标到下一行actionGo : Go,actionSearch : 放大镜actionSend : SendactionNext : NextactionDo ...

  6. 我曾经的第一个OC程序

    一. OC简介 C语言的基础上,增加了一层最小的面向对象语法 完全兼容C语言 可以在OC代码中混入C语言代码,甚至是C++代码 可以使用OC开发Mac OS X平台和iOS平台的应用程序 二. OC语 ...

  7. IOS OC声明变量在@interface括号中与使用@property的区别

    方式一:直接在@interface中的大括号中声明. @interface MyTest : NSObject{ NSString *mystr; } 方式二:在@interface中声明,然后再在@ ...

  8. 敏捷开发--scrum

    1.  请简述一下什么是敏捷开发(Agile Development),以及什么是持续集成.  敏捷开发是一种以人为核心.迭代.循序渐进的开发方法.在敏捷开发中,软件项目的构建被切分成多个子项目,各个 ...

  9. MySQL substring:字符串截取 (转载)

    MySQL 字符串截取函数:left(), right(), substring(), substring_index().还有 mid(), substr().其中,mid(), substr() ...

  10. layout 布局、手风琴accordion、选项卡tabs

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...