说说如何利用 Python 处理 CSV 文件

CSV 表示 “Comma-Separated Values (逗号分隔的值) ” , CSV 文件是简化的电子表格,实际为纯文本文件。

一个 CSV 文件,格式是这样的:

因为 CSV 文件中的每个单元格都是以逗号分割,所以也许有人会对每行文本调用 split() 方法,来解析 CSV 文件。但 CSV 文件也有自己的转义字符,通过转义字符,允许逗号和其他字符作为值的一部分,但单纯使用 split() 方法不能处理这些转义字符。因为这些潜在的缺陷,所以建议总是使用 csv 模块来读写 CSV 文件。

csv 模块是 Python 自带的,所以可以直接导入。

1 Reader 对象

要使用 csv 模块从 CSV 文件中读取数据,我们需要创建一个 Reader 对象。 通过 Reader 对象,我们可以迭代遍历 CSV 文件中的每一行内容。

import os

import csv
import logging

# logging.disable(logging.CRITICAL)
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s - %(message)s')
'''
读取 CSV
@author Deniro Li
'''
os.chdir('F:/temp')

file = open('CsvDataSource.csv')
reader = csv.reader(file)
data = list(reader)
logging.info('data -> %s', str(data))

运行结果:

INFO - data -> [['Dallas', '47', 'Janet Fuller', '445 Upland Pl.', 'Trial', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Lyon', '38', 'Andrew Heiniger', '347 College Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Dallas', '43', 'Susanne Smith', '2 Upland Pl.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Berne', '22', 'Bill Ott', '250 - 20th Ave.', 'Active', ' "47.21"', ' "8.31"', ' "1996-07-22 00:00:00"'], ['Boston', '32', 'Michael Ott', '339 College Av.', 'Trial', ' "42.21"', ' "-71.5"', ' "1996-07-22 00:00:00"'], ['Dallas', '4', 'Sylvia Ringer', '365 College Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Boston', '23', 'Julia Heiniger', '358 College Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Chicago', '39', 'Mary Karsen', '202 College Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Dallas', '40', 'Susanne Miller', '440 - 20th Ave.', 'Trial', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Berne', '9', 'James Schneider', '277 Seventh Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Dallas', '36', 'John Steel', '276 Upland Pl.', 'Suspended', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Chicago', '35', 'George Karsen', '412 College Av.', 'Suspended', ' "41.50"', ' "-87.37"', ' "1996-07-22 00:00:00"'], ['Dallas', '37', 'Michael Clancy', '19 Seventh Av.', 'Deleted', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Lyon', '2', 'Anne Miller', '20 Upland Pl.', 'Active', ' ""', ' "" ', ' "1996-07-22 00:00:00"'], ['Dallas', '0', 'Laura Steel', '429 Seventh Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Lyon', '28', 'Susanne White', '74 - 20th Ave.', 'Deleted', ' ""', ' "" ', ' "1996-07-22 00:00:00"'], ['Paris', '5', 'Laura Miller', '294 Seventh Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Lyon', '17', 'Laura Ott', '443 Seventh Av.', 'Active', ' "45.45"', ' "4.50" ', ' "1996-07-22 00:00:00"'], ['New York', '46', 'Andrew May', '172 Seventh Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['New York', '44', 'Sylvia Ott', '361 College Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Dallas', '19', 'Susanne Heiniger', '86 - 20th Ave.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Chicago', '11', 'Julia White', '412 Upland Pl.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Dallas', '10', 'Anne Fuller', '135 Upland Pl.', 'Active', ' "32.46"', ' "-96.46"', ' "1996-07-22 00:00:00"'], ['New York', '41', 'Bill King', '546 College Av.', 'Deleted', ' "40.47"', ' "-73.58"', ' "1996-07-22 00:00:00"'], ['Oslo', '45', 'Janet May', '396 Seventh Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Paris', '18', 'Sylvia Fuller', '158 - 20th Ave.', 'Trial', ' "48.48"', ' "2.20"', ' "1996-07-22 00:00:00"'], ['San Francisco', '48', 'Robert White', '549 Seventh Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['Paris', '25', 'Sylvia Steel', '269 College Av.', 'Suspended', ' ""', ' ""', ' "1996-07-22 00:00:00"'], ['San Francisco', '7', 'James Peterson', '231 Upland Pl.', 'Active', ' "37.47"', ' "-122.26"', ' "1996-12-12 00:00:00"'], ['Oslo', '42', 'Robert Ott', '503 Seventh Av.', 'Trial', ' "59.57"', ' "10.42"', ' "1996-09-09 00:00:00"']]

要用 csv 模块读取 CSV 文件,首先先使用 open() 函数打开它 ,就像打开任何其他文本文件一样。然后将它传递给 csv .reader() 函数。 这个函数将返回一个 Reader 对象。注意,csv .reader() 函数不接受文件名作为入参。

要访问 Reader 对象中的值,最直接的方法,就是利用 list() 将它转换成一个普通 Python 列表。它实际为一个包含列表的列表,用于表示二维数据。

我们还可以使用表达式 data [ row ][ col ] 来访问 CSV 中特定行和列的值。其中, row 是 data 中一个列表的下标, col 是该列表中,我们想访问的项的下标:

logging.info('data[0][0] -> %s', str(data[0][0]))
logging.info('data[2][3] -> %s', str(data[2][3]))
logging.info('data[5][2] -> %s', str(data[5][2]))

运行结果:

INFO - data[0][0] -> Dallas
INFO - data[2][3] -> 2 Upland Pl.
INFO - data[5][2] -> Sylvia Ringer

2 逐行读取

file = open('CsvDataSource.csv')
reader = csv.reader(file)
logging.debug('reader -> '+str(reader))
for row in reader:
    logging.info('Row #%d->  %s',reader.line_num, str(row))

运行结果:

DEBUG - reader -> <_csv.reader object at 0x0000000002716A08>
INFO - Row #1->  ['Dallas', '47', 'Janet Fuller', '445 Upland Pl.', 'Trial', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #2->  ['Lyon', '38', 'Andrew Heiniger', '347 College Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #3->  ['Dallas', '43', 'Susanne Smith', '2 Upland Pl.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #4->  ['Berne', '22', 'Bill Ott', '250 - 20th Ave.', 'Active', ' "47.21"', ' "8.31"', ' "1996-07-22 00:00:00"']
INFO - Row #5->  ['Boston', '32', 'Michael Ott', '339 College Av.', 'Trial', ' "42.21"', ' "-71.5"', ' "1996-07-22 00:00:00"']
INFO - Row #6->  ['Dallas', '4', 'Sylvia Ringer', '365 College Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #7->  ['Boston', '23', 'Julia Heiniger', '358 College Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #8->  ['Chicago', '39', 'Mary Karsen', '202 College Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #9->  ['Dallas', '40', 'Susanne Miller', '440 - 20th Ave.', 'Trial', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #10->  ['Berne', '9', 'James Schneider', '277 Seventh Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #11->  ['Dallas', '36', 'John Steel', '276 Upland Pl.', 'Suspended', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #12->  ['Chicago', '35', 'George Karsen', '412 College Av.', 'Suspended', ' "41.50"', ' "-87.37"', ' "1996-07-22 00:00:00"']
INFO - Row #13->  ['Dallas', '37', 'Michael Clancy', '19 Seventh Av.', 'Deleted', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #14->  ['Lyon', '2', 'Anne Miller', '20 Upland Pl.', 'Active', ' ""', ' "" ', ' "1996-07-22 00:00:00"']
INFO - Row #15->  ['Dallas', '0', 'Laura Steel', '429 Seventh Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #16->  ['Lyon', '28', 'Susanne White', '74 - 20th Ave.', 'Deleted', ' ""', ' "" ', ' "1996-07-22 00:00:00"']
INFO - Row #17->  ['Paris', '5', 'Laura Miller', '294 Seventh Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #18->  ['Lyon', '17', 'Laura Ott', '443 Seventh Av.', 'Active', ' "45.45"', ' "4.50" ', ' "1996-07-22 00:00:00"']
INFO - Row #19->  ['New York', '46', 'Andrew May', '172 Seventh Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #20->  ['New York', '44', 'Sylvia Ott', '361 College Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #21->  ['Dallas', '19', 'Susanne Heiniger', '86 - 20th Ave.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #22->  ['Chicago', '11', 'Julia White', '412 Upland Pl.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #23->  ['Dallas', '10', 'Anne Fuller', '135 Upland Pl.', 'Active', ' "32.46"', ' "-96.46"', ' "1996-07-22 00:00:00"']
INFO - Row #24->  ['New York', '41', 'Bill King', '546 College Av.', 'Deleted', ' "40.47"', ' "-73.58"', ' "1996-07-22 00:00:00"']
INFO - Row #25->  ['Oslo', '45', 'Janet May', '396 Seventh Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #26->  ['Paris', '18', 'Sylvia Fuller', '158 - 20th Ave.', 'Trial', ' "48.48"', ' "2.20"', ' "1996-07-22 00:00:00"']
INFO - Row #27->  ['San Francisco', '48', 'Robert White', '549 Seventh Av.', 'Active', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #28->  ['Paris', '25', 'Sylvia Steel', '269 College Av.', 'Suspended', ' ""', ' ""', ' "1996-07-22 00:00:00"']
INFO - Row #29->  ['San Francisco', '7', 'James Peterson', '231 Upland Pl.', 'Active', ' "37.47"', ' "-122.26"', ' "1996-12-12 00:00:00"']
INFO - Row #30->  ['Oslo', '42', 'Robert Ott', '503 Seventh Av.', 'Trial', ' "59.57"', ' "10.42"', ' "1996-09-09 00:00:00"']

3 Writer 对象

Writer 对象可以让我们把数据写入 CSV 文件。

import csv
import os

'''
写入 csv
@author Deniro Li
'''

os.chdir('F:/temp')

output_file = open('output.csv', 'w', newline='')
output_writer = csv.writer(output_file)
output_writer.writerow(['网页', '咨询', '视频'])
output_writer.writerow(['图片', '知道', '文库'])
output_file.close()

运行结果:


  1. 首先调用 open()并传入'w',以写模式打开一个新文件;
  2. 然后使用 csv.writer() 函数,创建一个 Writer 对象;
  3. 接着写入数据;
  4. 最后关闭这个文件。

在 Windows 上,需要为 open() 函数的 newline 关键字参数传入一个空字符串。如果没有设置 newline 参数, output.csv 中的行距将变为两倍,如下图所示。


如果写入的内容包含逗号,那么 csv 模块会自动加上双引号,对其进行转义,如下例所示。

output_writer.writerow(['贴吧,采购', '知道', '文库'])

运行结果:


4 delimiter 和 lineterminator

我们也可以利用 delimiter ,来制作 TSV 文件,TSV 是Tab-separated values的缩写,即以制表符作为分隔符的文件;利用 lineterminator 参数来设定行距。

tsv_file = open('output.tsv', 'w', newline='')
output_writer = csv.writer(tsv_file, delimiter='\t', lineterminator='\n\n\n')
output_writer.writerow(['网页', '咨询', '视频'])
output_writer.writerow(['图片', '知道', '文库'])
output_writer.writerow(['贴吧,采购', '知道', '文库'])
tsv_file.close()

运行结果:


这里利用 lineterminator='\n\n\n' 将行与行之间的字符变为三个换行符,效果就是实现了 3 倍行距。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容