今天的练级主题是Python的csv模块,直接找到Python官方文档的csv模块页:
http://docs.python.org/2/library/csv.html#module-csv
首先,我做了一个稍不是很正常的excel文档来做测试,文档内容如图,
为什么不是很正常呢,因为本来就是","分割的值表,如果值里面包含了","怎么办?观察产生的csv的文本:
这里之所以要截图不用文本的复制粘贴,下文有玄机。这个文档除了值中包含","还包含了双引号和单引号,因此用自己写程序读这个file可能难免会出BUG,至少不能像昨天一样简单的.split(",")可以搞定了。
所以今天要学用的就是csv模块,首先import。
>>> import csv >>>
然后打开文档看看,
>>> with open('HelloWorld.csv') as csvfile: ... print csvfile.read() ... "4,,5",7&8,That's it,,,,1+2 >>>
前面这个with open是csv模块官方文档给的一个语句结构,Google了一下,用with打开的一个好处是会自己擦屁股,比如with open之后会自动close()。除此之外,个人理解"with open(filename) as f" == "f = open(filename)",如果有高手觉得这个我说的不对的话,请不吝赐教。
说完with之后,发现这个print出来的东西不对!前面两行直接被吞掉了,查看了一下不是with的问题。而是open的问题,本来open这个内置函数应该是明天的练级主题,既然今天出来了,当然也十分欢迎。看一下open的官方文档说明。
首先是open的语法
open(name[, mode[, buffering]])
里面的模式(mode)参数中,'r','w','a'分别代表只读,写入和增加,这个估计都早知道了,对于个人来说比较新的是'U'和'b','b'是支持二进制打开,即使文档不是二进制文件,使用这个参数也没有坏处,'U'是支持universal newlines的参数,所谓universal newlines的意思是各个操作系统平台所用的换行附是不同的,比如'\n'是Python默认的换行符,'\r\n'则是windows上默认的,此外还有'\r'和'^M',就是本文所产生的csv文档中所使用的换行符,这也是为什么之前要使用截图而不是直接复制粘贴文字的原因,写了那么多直接来个测试看看用'U'模式打开文档会不会有区别。
>>> with open('HelloWorld.csv','Urb') as csvfile: ... print csvfile.read() ... 1,"2,3",4.5,5-6,7/8,9~0,1+2 """11""",12,19%,#123,,, "4,,5",7&8,That's it,,,, >>>
很好,3行都print出来了。
但是光Print出来只是第一步,我们希望把这个东西放到一个列表或者字典里,csv模块提供了很有用的两个参数,一个是delimiter分割符默认是',',另一个是quotechar引用符,默认是'"',在这个例子里,直接用默认就好,话说这个虽然叫csv模块,但是改成处理tsv文档也就改一个参数的问题。
>>> with open('HelloWorld.csv','Urb') as csvfile: ... content = csv.reader(csvfile) ... for line in content: ... print line ... ['1', '2,3', '4.5', '5-6', '7/8', '9~0', '1+2'] ['"11"', '12', '19%', '#123', '', '', ''] ['4,,5', '7&8', "That's it", '', '', '', ''] >>>
由此,我发现了两点,一是这个reader的返回值是一个迭代器,另一点是这个迭代器yeild的每一项都是经过split之后的list对象。
我接下来尝试了一下csv.writer方法
>>> with open('HelloWorld.tab','wb') as tabfile: ... tabwriter = csv.writer(tabfile, delimiter='\t', quotechar='"') ... tabwriter.writerow(['Spam']*5) ... tabwriter.writerow(['Hello','World']) ... >>> content = [] >>> for line in csv.reader(open('HelloWorld.csv','Urb')): ... content.append(line) ... >>> with open('HelloWorld.tab','wb') as tabfile: ... tabwriter = csv.writer(tabfile, delimiter = '\t', quotechar='"') ... for line in content: ... tabwriter.writerow(line) ... >>> print open("HelloWorld.tab").read() 1 2,3 4.5 5-6 7/8 9~0 1+2 """11""" 12 19% #123 4,,5 7&8 That's it >>>
个人觉得csv的writer使用感觉不是那么好,首先writer很像一个handle,需要使用writer.writerow()才能写入,第二,一行一行写,写入的对象类型需要一维列表,一整块地写入则需要一个二维列表,相对麻烦。第三,没有.close()方法,需要用f.close()直接close整个file,或者用with打开file。关于这些“缺点”,如果有理解的不对的话,请高手们不吝赐教。
最后我尝试了一下使用dictreader和dictwriter,虽然最后查到了一个靠谱的使用方法:
http://bytes.com/topic/python/answers/910694-how-parse-csv-using-dictreader
但是我觉得这个用法比较晦涩,至少目前我如果想实现类似的功能,我会用更简单易懂粗暴的方法。
嗯,今天的csv模块就先到这,本来明天的open函数似乎也在今天解决了,那么下次的任务就是sys模块了,嘿嘿,那可是个很好用的模块,估计下次还会顺带着学习一下os模块哦。
===============================================================================
附:
这些“习题”源自陈皓叔叔的博文《程序员练级技术攻略》:
http://coolshell.cn/articles/4990.html
我希望尝试跟着他推荐的方式练级,同时把每日的心得放到博客上来供大家分享,也希望各位程序员大牛们指导。