刚开始学习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. Harp – 内置常用预处理器的静态 Web 服务器

    Harp 是一个基于 Node.js 平台的静态 Web 服务器,内置流行的预处理器,支持把 Jade, Markdown, EJS, Less, Stylus, Sass, and CoffeeSc ...

  2. 【javascript激增的思考02】模块化与MVC

    前言 之前我们遇到了这么一个项目,也就是我们昨天提到的,有很多的小窗口的,昨天说的太抽象了,今天我们再来理一理什么是小窗口(后面点说下),当时由于js有一点复杂,我自己也装B跟风用了一下传说中MVC! ...

  3. 深入理解javascript---如何编写高质量的代码?

    如何书写可维护的代码? 最小全局变量 JavaScript通过函数管理作用域.在函数内部声明的变量只在这个函数内部,函数外面不可用.另一方面,全局变量就是在任何函数外面声明的或是未声明直接简单使用的( ...

  4. HTML <a> 标签

    一,定义和用法 所有浏览器都支持 <a> 标签. <a> 标签定义超链接,用于从一张页面链接到另一张页面. <a> 元素最重要的属性是 href 属性,它指示链接的 ...

  5. ae动态显示属性表————切记DataTable中要先Add(row)之后再往里传值。

    public partial class FrmAttributeTable : Form { private AxMapControl m_MapCtl; public FrmAttributeTa ...

  6. Java Android HTTP实现总结

    Java Android HTTP实现总结 Http(Hypertext Transfer Protocol)超文本传输协议,是一个基于请求/响应模式的无状态的协议,Http1.1版给出了持续连接的机 ...

  7. Android 使用xml序列化器生成xml文件

    在<Android 生成xml文件>一文中使用流的形式写入xml格式文件,但是存在一定的问题,那就是在短信内容中不能出现<>之类的括号,本文使用xml序列化器来解决 xml序列 ...

  8. 你真的了解UIResponder吗?

    1:首先查看一下关于UIResponder的定义 NS_CLASS_AVAILABLE_IOS(2_0) @interface UIResponder : NSObject //响应链中负责传递事件的 ...

  9. iOS如何获取网络图片(三)有沙盒的

    沙盒 沙盒简介 默认情况下,每个沙盒含有3个文件夹:Documents, Library 和 tmp.因为应用的沙盒机制,应用只能在几个目录下读写文件 Documents:苹果建议将程序中建立的或在程 ...

  10. jsp学习笔记一

    page属性 定义JSP文件中的全局属性. 实例: <%@ page language="java" contentType="text/html; charset ...