介绍csv 模块前,需要先了解csv 文件(.csv 文件格式),csv 文件中的每行代表电子表格中的一行,并用逗号分隔该行中的单元格。
csv 文件可以使用记事本打开,可以使用Excel 另存为.csv 文件格式,或者在文本编辑器中输入文本,保存为.csv 文件格式。
csv 文件是比较简单的文件格式,缺少Excel 电子表格的许多功能。例如:
值没有类型,所有数据都是字符串。
没有字体大小和颜色的设置。
没有多个工作表。
不能指定单元格的宽度和高度。
不能合并单元格。
不能嵌入图像或图表。
csv 文件被应用程序广泛支持的原因,也正因为它的简单。它可以在文本编辑器中查看(包括IDLE 的文件编辑器),是表示电子表格数据的直接方式。
csv 模块的产生要从csv 文件说起:
csv 文件其实就是一个文本文件,用逗号分隔其值。因此,在Python 中可以使用split() 方法读取其中的值。如果csv 文件中的文本数据中包含逗号,那么csv 文件会进行转义,但是split() 方法却不能处理这些转义字符,另外还有一些其他方面的问题。这种情况下就产生了csv 模块,通过该模块来读写csv 文件,解决Python 读写csv 文件时所遇到的一些麻烦。csv 模块是实现以CSV 格式读取和写入表格数据的类。它可以定制其他应用程序适用的CSV 格式或定义自己的专用CSV 格式,还包括一些类和方法等,其中reader 类和writer 类用于读写序列化的数据,而DictReader 类和DictWriter 类将以字典的形式读写数据。
使用writer 对象写入数据时,当quoting 参数设置为QUOTE_ALL 常量时,表示对所有字段加入引用符。语法格式如下:
csv.QUOTE_ALL
参数说明:
使用writer 对象向csv 文件写入数据时,通过设置QUOTE_ALL 常量对所有字段使用管道符“|”,代码如下:
import csv
with open('a1.csv', 'w', newline='') as csvfile:
spamwriter = csv.writer(csvfile, delimiter=' ',
quotechar='|', quoting=csv.QUOTE_ALL)
spamwriter.writerow(['mrkj'] * 5 + ['www.mingrisoft.com'])
spamwriter.writerow(['mrkj', 4006751066, 84978981])
使用writer 对象写入数据时,当quoting 参数设置为QUOTE_MINIMAL 常量时,表示只对包含特殊字符的字段加入引用符。语法格式如下:
csv.QUOTE_MINIMAL
参数说明:
使用writer 对象向csv 文件写入数据时,通过设置QUOTE_MINIMAL 常量对包含特殊符号(如“&”“$”等)的字段加入引用符“|”,代码如下:
import csv
with open('a2.csv', 'w', newline='') as csvfile:
spamwriter = csv.writer(csvfile, delimiter=' ',
quotechar='|', quoting=csv.QUOTE_MINIMAL,escapechar='$')
spamwriter.writerow(['mrkj'] * 5 + ['www.mingrisoft.com'])
spamwriter.writerow(['mrkj&^%$$', 4006751066, 84978981])
QUOTE_NONE 常量是引用字段模式中的一种,用于告诉程序,csv 文件里不加入引用符。例如,csv 文件中的文本数据本身存在逗号,而csv 文件中又使用逗号作为分隔符,那么文本数据本身存在的逗号也会被当作分隔符,不管它在不在引用符里面。这种情况下可以设置QUOTE_NONE 常量,对所有字段不加引用符。语法格式如下:
csv.QUOTE_NONE
参数说明:
当使用writer 对象写入数据时,通过设置QUOTE_NONE 常量对所有字段都不使用引用符,代码如下:
import csv
with open('a3.csv', 'w', newline='') as csvfile:
spamwriter = csv.writer(csvfile, delimiter=' ',
quotechar='|', quoting=csv.QUOTE_NONE)
spamwriter.writerow(['mrkj'] * 5 + ['www.mingrisoft.com'])
spamwriter.writerow(['mrkj', 4006751066, 84978981])
使用writer 对象写入数据时,当quoting 参数设置为QUOTE_NONNUMERIC 常量时,表示对所有非数字的字段加入引用符。语法格式如下:
csv.QUOTE_NONNUMERIC
参数说明:
通过设置QUOTE_NONNUMERIC 常量实现向csv 文件写入数据时对非数字的字段加入分隔符,代码如下:
import csv
with open('a1.csv', 'w', newline='') as csvfile:
spamwriter = csv.writer(csvfile, delimiter=' ',
quotechar='|', quoting=csv.QUOTE_NONNUMERIC)
spamwriter.writerow(['mrkj'] * 5 + ['www.mingrisoft.com'])
spamwriter.writerow(['mrkj', 4006751066, 84978981])
Error 方法用于捕获和报告错误。语法格式如下:
csv.Error
参数说明:
使用Error 方法捕获和报告错误,代码如下:
import csv, sys
filename = 'mrdata.csv'
with open(filename, newline='') as f:
reader = csv.reader(f)
try:
for row in reader:
print(row)
except csv.Error as e:
sys.exit('file {}, line {}: {}'.format(filename, reader.line_num, e))
get_dialect() 方法用于获取与csv 文件指定名称(参数name)相关的编码风格,如果name 不是已注册的编码风格,那么将会引发错误。语法格式如下:
csv.get_dialect(name)
参数说明:
name:表示已注册的csv文件编码风格,如果name参数值不是已注册的csv文件编码风格,则会引发错误。
返回值:返回不可变的Dialect类。
获取csv 文件的编码风格使用get_dialect() 方法获取csv 文件的编码风格,代码如下:
import csv
csv.register_dialect('mr',delimiter='|',quoting=csv.QUOTE_NONE)
print(csv.get_dialect('excel'))
print(csv.get_dialect('mr'))
print(csv.list_dialects())
list_dialects() 方法用于返回所有已注册的csv 文件编码风格列表。语法格式如下:
csv.list_dialects()
参数说明:
使用list_dialects() 方法获取csv 文件已注册的编码风格列表,代码如下:
import csv
print(csv.list_dialects())
reader() 方法用于读取csv 文件。语法格式如下:
csv.reader(csvfile, dialect='excel', **fmtparams)
参数说明:
csvfile:必须是支持迭代器的reader 对象,可以是文件(file 对象)。
dialect:表示csv文件的编码风格,默认为excel方式,也就是用逗号“,”分隔。dialect也支持自定义,通过调用register_dialect() 方法注册新的编码风格,该方法在13.10 节讲解。
**fmtparams:格式参数。
返回值:返回一个reader 对象,该对象将迭代遍历给定的csv文件中的行。
使用reader() 方法简单读取csv 文件,并传入一个文件对象。由于reader() 方法返回的是一个可迭代的对象,因此需要使用for 循环实现遍历,代码如下:
import csv
with open(‘r1.csv’) as myFile: # 打开csv文件
rows=csv.reader(myFile) # 读取csv文件
print(rows)
for row in rows: # 按行读取
print(‘,’.join(row))
中变量row 是一个列表,如果想要提取csv 文件中某列数据,则需要指定上下标。例如,查看“运单号”列数据,那么只需要改为row[0],具体代码如下:
import csv
with open(‘r1.csv’) as myFile: # 打开csv文件
rows=csv.reader(myFile) # 读取csv文件
for row in rows: # 按行读取
print(row[0]) # 第0列
提取csv 文件某行数据,需要在循环语句中使用enumerate() 函数将读取后的csv 文件数据组合为一个索引序列,这个序列中包含了数据和数据下标,当下标为指定行时,提取该行数据。例如,获取第二行数据,代码如下:
import csv
with open(‘r1.csv’) as myFile: # 打开csv文件
data=csv.reader(myFile) # 读取csv文件
for i,rows in enumerate(data): # 按行读取
if i==2: # 如果行号为2,提取该行数据
row=rows
print(row)
程序运行结果如下:
['7515124', '2019/6/1', '888科技有限公司', '上海', '上海市', '1.15', '杨浦', '杨浦', '2019/6/3
19:58', '10']
说明:如果提取前几行(如前5 行),则将if 语句的条件改为:i<5。如果不要表头,则将if 语句的条件改为:i!=0。如果提取指定范围的行(如第1 行~ 第4 行),则将if 语句的条件改为:if 1<=i<=4。
查看特定行和列的数据,需要将reader() 方法返回的reader 对象转换成Python 列表,然后指定列表的上下标来读取特定行和列的数据,如读取第1 行第4 列的数据,代码如下:
import csv
with open(‘r1.csv’) as myFile: # 打开csv文件
rows=csv.reader(myFile) # 读取csv文件
mydata=list(rows) # 转换成Python列表
print(mydata[1][4]) # 打印特定行和列的数据
程序运行结果如下:
秦皇岛市
方法1 :指定行读取表头。通过指定行来读取csv 文件的表头数据,代码如下:
import csv
with open('r1.csv') as f:
reader = csv.reader(f)
rows=[row for row in reader]
print(rows[0])
使用next() 方法读取csv 文件的表头数据,代码如下:
import csv
with open(‘r1.csv’) as f:
# 创建reader对象
reader = csv.reader(f)
# 读取第1行数据
h1=next(reader)
print(h1)
程序运行结果如下:
['运单号', '账单日期', '结算对象', '目的地', '城市', '结算重量', '派件网点', '签收网点', '签收时间', '客户运费']
首先使用reader() 方法读取第1 行数据,然后使用enumerate() 函数遍历该数据对象组合成一个索引序列,同时列出数据和数据下标(也就是列名及其索引),代码如下:
import csv
with open(‘r1.csv’) as f:
# 创建reader对象
reader = csv.reader(f)
# 读取第1行数据
h1=next(reader)
# 使用enumerate()函数获取表头及其索引
for index,column in enumerate(h1):
print(index,column)
程序运行结果如下:
0 运单号
1 账单日期
2 结算对象
3 目的地
4 城市
5 结算重量
6 派件网点
7 签收网点
8 签收时间
9 客户运费
首先使用reader() 方法读取数据,然后将要计算最大值的列(如“销量”)保存为列表,之后再使用max() 函数求该列最大值,代码如下:
import csv
with open(‘mrbook1.csv’) as f:
# 读取数据
reader = csv.reader(f)
h1=next(reader)
myval=[]
for row in reader:
# 将“销量”列保存到myval列表中
myval.append(int(row[4]))
print(myval)
print(‘当日最高销量:'+str(max(myval))+’本')
程序运行结果如下:
[1300, 2355, 110, 120, 541, 120, 120, 271, 625, 888, 333, 241, 120, 663, 888, 559, 281,148, 120, 456, 322, 120, 120, 129, 120, 354, 248]
当日最高销量:2355本
在向csv 文件写入数据或追加数据或处理数据时,有时需要判断csv 文件是否有表头,以免添加重复或进行其他处理。下面通过检测第1 行数据的长度是否为0 来判断是否有表头,代码如下:
import csv
header = True
# 打开文件
with open( ‘r1.csv’, ‘r’ ) as f :
reader = csv.reader( f )
header = [r for r in reader ]
if len( header ) == 0 :
header = False
print( ‘csv文件无表头!’ )
else:
header = True
print( ‘csv文件有表头!’ )
程序运行结果如下:
csv文件有表头!
使用reader() 方法读取csv 文件数据,然后将其转换成dataframe 格式,代码如下:
import csv
import pandas as pd
# 解决输出dataframe格式数据不对齐,显示不全的问题
pd.set_option(‘display.unicode.ambiguous_as_wide’, True)
pd.set_option(‘display.unicode.east_asian_width’, True)
pd.set_option(‘display.max_columns’,500)
pd.set_option(‘display.width’,1000)
# 读取csv文件数据
lines=list(csv.reader(open(r’r1.csv’)))
header,values=lines[0],lines[1:]
data1={h:v for h,v in zip(header,zip(*values))}
df=pd.DataFrame(data1) # 转换成dataframe格式
print(df)
register_dialect() 方法用于注册一个新的csv 文件编码风格。语法格式如下:
csv.register_dialect(name[,dialect [,**fmtparams]])
参数说明:
name:必须是一个字符串,要注册的csv文件编码风格的名称。
dialect:Dialect子类。
**fmtparams:格式参数。
返回值:返回已注册的csv文件编码风格。
使用register_dialect() 方法注册一个新的csv 文件编码风格。例如,编码风格名称为“mr”,并读取该编码风格的文件,代码如下:
import csv
csv.register_dialect('mr',delimiter='|',quoting=csv.QUOTE_NONE)
print(csv.list_dialects())
with open('mrdata.mr',newline='') as f:
reader=csv.reader(f,'mr')
for row in reader:
print(row)
unregister_dialect() 方法用于从注册表中删除新注册的csv 文件的编码风格。语法格式如下:
csv.unregister_dialect(name)
参数说明:
name:必须是一个字符串,新注册的csv 文件的编码风格名称。如果name 参数值不是新注册的csv 文件的编码风格名称,则会引发错误。
返回值:无。
使用unregister_dialect() 方法注销新注册的csv 文件的编码风格“mr”。首先使用register_dialect()方法注册一个新的csv 文件的编码风格“mr”,然后使用unregister_dialect() 方法将其注销,代码如下:
import csv
csv.register_dialect('mr',delimiter='|',quoting=csv.QUOTE_NONE)
print(csv.list_dialects())
csv.unregister_dialect('mr')
print(csv.list_dialects())
writer() 方法用于将数据写入csv 文件。语法格式如下:
csv.writer(csvfile,dialect =’excel’,**fmtparams )
参数说明:
csvfile:必须是支持迭代器的writer 对象,可以是文件(file 对象)。
dialect:csv 文件的编码风格,默认为excel 编码风格,也就是用逗号“,”分隔,csv 文件的编码风格也支持自定义,通过调用register_dialect() 方法注册新的编码风格,该方法已在13.10 节讲解。
**fmtparams:格式参数。
返回值:返回一个writer 对象。
使用writer() 方法将数据写入到csv 文件中,代码如下:
import csv
# 写入数据
with open('w1.csv', 'w', newline='') as f:
csvw = csv.writer(f)
csvw.writerow(['mrkj'] * 5 + ['www.mingrisoft.com'])
csvw.writerow(['mrkj', '4006751066', '0431-84978981'])
# 读取数据
with open('w1.csv') as myFile: # 打开csv文件
rows=csv.reader(myFile) # 读取csv文件
for row in rows: # 按行读取
print(','.join(row))
写入数据时,系统自动使用逗号分隔单元格数据。下面将用制表符代替逗号分隔单元格数据,代码如下:
import csv
with open(‘w2.csv’, ‘w’,newline=’’) as f: # 如不指定newline=’’,有时会写入空行
writer = csv.writer(f,delimiter=’\t’, lineterminator=’\n\n’)
writer.writerow([‘订单编号', ‘会员名', ‘商品名称']) # 写入一行标题
writer.writerow([‘mr00001’,’mrsoft’,’零基础学Python’]) # 写入一行数据
writer.writerow([‘mr00002’,’mingri’,’Python从入门到项目实践']) # 写入一行数据
with open(‘w2.csv’) as myFile: # 打开csv文件
rows=csv.reader(myFile) # 读取csv文件
for row in rows: # 按行读取
print(‘,’.join(row))
在Python 中,以a+ 的方式打开文件表示追加。下面向原有运费数据表r1.csv 中追加两条新数据,代码如下:
import csv
# 以a+的方式打开文件表示追加
with open(‘r1.csv’, ‘a+’,newline=’’) as f:
csv_write=csv.writer(f)
a =[‘7515131’,’2019/6/12’,’明日科技',’吉林省',’长春市',’3’,’长春二道',’长春二道',’2019/6/15’,’5’]
b=[‘7515132’,’2019/6/12’,’明日科技',’吉林省',’四平市',’2’,’长春二道',’长春二道',’2019/6/15’,’6’]
csv_write.writerow(a)
csv_write.writerow(b)
原有csv 文件包括“定价”列和“销量”列,通过这两列相乘可以得出“金额”列,将该列追加到原csv 文件中,代码如下:
import csv
with open('mrbook1.csv') as csvFile:
rows = csv.reader(csvFile)
h1=next(rows)
with open('mrbook2.csv', 'w',newline='') as f:
writer = csv.writer(f)
for row in rows:
row.append(float(row[3])*int(row[4])) # 追加一列“金额”
writer.writerow(row) # 在每行的最后一列写入“金额”
使用writer() 方法将dataframe 格式数据写入到csv 文件,代码如下:
import csv
import pandas as pd
# 读取csv文件数据
lines=list(csv.reader(open(‘r1.csv’)))
header,values=lines[0],lines[1:]
data1={h:v for h,v in zip(header,zip(*values))}
df=pd.DataFrame(data1) # 转换成dataframe格式
# 使用writer()方法将dataframe格式数据写入csv文件
rows = df.values
with open(‘r1副本.csv’, ‘w+’, newline=’’) as csv_file:
writer = csv.writer(csv_file)
writer.writerow(df.columns)
for row in rows:
writer.writerow(row)
由于csv 文件太大无法读取或是由于工作需要,有时需要将一个csv 文件分割为多个csv 文件。这种情况可以先读取数据,对数据按条数进行分割,然后再将数据写入到新文件中。
import csv
import os
path = ‘222.csv’
with open(path, ‘r’, newline=’’) as f:
data = csv.reader(f)
a = next(data)
print(a)
i = j = 1
for row in data:
print(row)
print(f’i is {i}, j is {j}’)
# 每10条数据进行分割,并生成新的文件名
if i % 10 == 0:
j += 1
print(f’文件{j} 生成成功')
path = ‘./aa/’ + str(j) + ‘.csv’
print(path)
# 如果文件不存在,则创建文件并写入数据
if not os.path.exists(path):
with open(path, ‘w’, newline=’’) as f:
w = csv.writer(f)
w.writerow([‘n1’,’n2’,’n3’,’n4’])
w.writerow(row)
i += 1
# 如果文件存在,则追加写入数据
else:
with open(path, ‘a’, newline=’’) as f:
w = csv.writer(f)
w.writerow(row)
i += 1
csv 文件中的格式有很多,如逗号分隔、冒号分隔等,我们可以自己定义一个Dialect 类,在该类中规定格式,以读取或写入csv 文件。语法格式如下:
csv.Dialect
参数说明:
自定义一个Dialect 类,设置分隔符、字符串引用约定、行结束符等,代码如下:
import csv
class my_dialect(csv.Dialect):
lineterminator = '\n'
delimiter = ';'
quotechar = '|'
with open('mrdata.csv','r') as f:
reader = csv.reader(f, dialect=my_dialect,quoting=csv.QUOTE_ALL)
for row in reader:
print(row)
delimiter 属性用于定义字段之间使用的分隔符,默认为逗号“,”。语法格式如下:
Dialect.delimiter
参数说明:
分隔符用于对csv 文件的字段进行分隔,典型分隔符有逗号“,”、分号“;”、制表符“\t”、管道符“|”等,有时分隔符还可以包括可选的空格。例如,Windows 系统的csv 文件使用逗号、Mac 系统的csv 文件使用分号、而大型的csv 文件一般会使用管道符“|”。这些分隔符都可以通过delimiter属性设置。下面设置csv 文件字段之间的分隔符为分号“;”,代码如下:
import csv
with open(‘b1.csv’, ‘w’, newline=’’) as csvfile:
spamwriter = csv.writer(csvfile, delimiter=’;',quotechar=’|’)
spamwriter.writerow([‘mrkj’] * 5 + [‘www.mingrisoft.com’])
spamwriter.writerow([‘mrkj’, 4006751066, 84978981])
csv 模块在Windows 系统中默认使用的是excel 编码风格,分隔符为逗号,而Mac 系统中csv 文件的分隔符是分号,此时使用reader() 方法直接读取就会出现如图21 的效果。要解决这一问题,应在读取csv 文件时,将字段之间的分隔符设置为分号,与Mac 系统中csv 文件保持一致,即设置delimiter 属性值为“;”,代码如下:
import csv
with open(‘numMAC.csv’) as myFile: # 打开csv文件
data=csv.reader(myFile,delimiter=’;’) # 读取csv文件,设置分隔符为分号“;”
for r in data:
print(r)
doublequote 属性提供了一种解决引用符里出现引用符问题的文件规范,默认值为True。语法格式如下:
Dialect.doublequote
参数说明:
当csv 文件数据中存在与引用符相同的符号时,例如,引用符为引号“‘’”,而csv 文件中的数据也有该符号,那么在该符号的位置将会出现两次引号“‘’”。如果doublequote 值为False,且没有指定转义字符(设置escapechar 参数)的情况下,程序就会出现错误提示。
通过设置doublequote 属性为True 为字段添加双引用符。例如,写数据时,“mrk’‘j”中包含引用符“’'”,那么需为该字段添加双引用符,代码如下:
import csv
with open('b1.csv', 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=' ',quotechar='"',doublequote=True,quoting=csv.QUOTE_ALL)
writer.writerow(['mrk"j'] * 5 + ['www.mingrisoft.com'])
writer.writerow(['mrkj', 4006751066, 84978981])
程序运行结果如下:
"mrk""j" "mrk""j" "mrk""j" "mrk""j" "mrk""j" "www.mingrisoft.com" "mrkj" "4006751066" "84978981"
如果csv 文件的文本数据中存在有符号,并且与我们使用的引用符一样,那么程序将自动出现双引用符,而这样的数据就会显得不是很清晰。此时,可以设置doublequote 属性值为False,不让它出现双引用符,但是程序又会出现如图23 所示的错误提示。
这种情况下我们需要设置escapechar 属性,也就是设置转义字符,将同引用符相同的符号进行转义。例如,将上一实例中数据“mrk’‘j”中的“’'”转义为百分号“%”,代码如下:
import csv
with open('b1.csv', 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=' ',quotechar='"',doublequote=False,quoting=csv.QUOTE_ALL,escapechar='%')
writer.writerow(['mrk"j'] * 5 + ['www.mingrisoft.com'])
writer.writerow(['mrkj', 4006751066, 84978981])
在向csv 文件写入或读取数据时,通过设置escapechar 属性在文本中使用转义字符,默认是None,不使用转义字符。语法格式如下:
Dialect.escapechar
参数说明:
向csv 文件写入数据时,为特殊的文本加上转义字符。例如,为银行卡号加“-”,代码如下:
import csv
with open(‘mrdata1.csv’, ‘w’, newline=’’) as f:
writer = csv.writer(f, delimiter=’ ‘,quotechar=’|’, quoting=csv.QUOTE_NONE,escapechar=’-’)
writer.writerow([‘编号',’员工姓名', ‘卡号', ‘备注'])
writer.writerow([‘mr001’, ‘高猿员', ‘6229 9999 123’,’mr’])
writer.writerow([‘mr002’, ‘小李', ‘6222 8888 456’,’mr’])
将使用了转义字符的文本还原为原有的样式,代码如下:
import csv
with open(‘b1.csv’,newline=’’)as f:
# 读取csv文件
rows=csv.reader(f,delimiter=’ ‘,quotechar=’”’,quoting=csv.QUOTE_ALL,escapechar=’%’)
for row in rows: # 按行读取
print(‘,’.join(row))
lineterminator 属性用于向csv 文件写入数据时设置行的结束符,默认为“‘\r\n’”。读数据操作时将忽略此选项。语法格式如下:
Dialect.lineterminator
参数说明:
向csv 文件写入数据时,通过设置lineterminator 属性使用管道符“|”作为一行的结束符,代码如下:
import csv
with open(‘mrdata2.csv’, ‘w’, newline=’’) as f:
writer = csv.writer(f, delimiter=’ ‘,quotechar=’|’, quoting=csv.QUOTE_NONE,lineterminator=’|’)
writer.writerow([‘编号',’员工姓名', ‘卡号', ‘备注'])
writer.writerow([‘mr001’, ‘高猿员', ‘62299999123’,’mr’])
writer.writerow([‘mr002’, ‘小李', ‘62228888456’,’mr’])
quotechar 属性用于定义字段的引用符,默认为双引号。引用符都是成对出现的,当csv 文件中的文本数据中出现了csv 文件使用的分隔符,此时将使用引用符将它括起来以排除歧义。语法格式如下:
Dialect.quotechar
参数说明:
通过设置quotechar 属性使用百分号“%”来引用字段,代码如下:
import csv
with open(‘mrdata3.csv’, ‘w’, newline=’’) as f:
writer = csv.writer(f, delimiter=’ ‘,quotechar=’%’, quoting=csv.QUOTE_ALL)
writer.writerow([‘编号',’员工姓名', ‘卡号', ‘备注'])
writer.writerow([‘mr001’, ‘高猿员', ‘62299999123’,’mr’])
writer.writerow([‘mr002’, ‘小李', ‘62228888456’,’mr’])
对csv 文件使用百分号“%”作为分隔符,恰巧csv 文件中的文本数据也存在百分号“%”,如’ 小% 李’,这时可通过设置quotechar 属性来区分,代码如下:
import csv
with open(‘mrdata3.csv’, ‘w’, newline=’’) as f:
writer = csv.writer(f, delimiter=’%’,quotechar=’”’, quoting=csv.QUOTE_ALL)
writer.writerow([‘编号',’员工姓名', ‘卡号', ‘备注'])
writer.writerow([‘mr001’, ‘高猿员', ‘62299999123’,’mr’])
writer.writerow([‘mr002’, ‘小%李', ‘62228888456’,’mr’])
quoting 属性用来设置什么情况下对字段使用引用符。语法格式如下:
Dialect.quoting
参数说明:
返回值:无。
quoting 属性的设置值如下:
Ø csv.QUOTE_ALL :writer 对象写入数据时对所有字段加入引用符。
Ø csv.QUOTE_MINIMAL :writer 对象写入数据时只对包含特殊字符的字段加入引用符。
Ø csv.QUOTE_NONE :writer 对象写入数据时对所有字段不加引用符。
Ø csv.QUOTE_NONNUMERIC :writer 对象写入数据时对所有非数字的字段加入引用符。
当使用writer 对象写入数据时,代码中设置了字段的引用符“%”,代码如下:
import csv
with open(‘mrdata3.csv’, ‘w’, newline=’’) as f:
writer = csv.writer(f, delimiter=’ ‘,quotechar=’%’, quoting=csv.QUOTE_ALL)
writer.writerow([‘编号',’员工姓名', ‘卡号', ‘备注'])
writer.writerow([‘mr001’, ‘高猿员', ‘62299999123’,’mr’])
writer.writerow([‘mr002’, ‘小李', ‘62228888456’,’mr’])
DictReader 类用于为读取的csv 文件创建一个有序字典的可读取的csv 文件对象。语法格式如下:
csv.DictReader(f,fieldnames=None,restkey=None,restval=None,dialect='excel',*args,**kwds)
参数说明:
f :文件对象。
fieldnames:字段名称。如果省略fieldnames参数,则文件f 的第一行中的值将作为字段名。
restkey:如果一行包含的字段多于字段名,则将剩余的数据存放在一个列表中,并使用restkey参数指定的字段名(默认为None)进行存储。如果非空行的字段少于字段名,则缺少的值将填入None。
restval:如果csv文件缺少指定的字段名,则使用可选参数restval指定要写入的值。
dialect:支持excel格式的csv编码风格。
*args :不定数量的非键值对参数(格式参数)。
**kwds:不定数量的键值对参数(格式参数)。
返回值:返回csv文件对象。
使用DictReader 类读取test_csv_data.csv 文件中的数据,代码如下:
import csv
with open('test_csv_data.csv',newline='')as csvfile:
reader=csv.DictReader(csvfile)
for row in reader:
print(row)
程序运行结果如下:
OrderedDict([('订单编号', 'mr00001'), ('会员名', 'mrsoft')])
OrderedDict([('订单编号', 'mr00002'), ('会员名', 'mingri')])
OrderedDict([('订单编号', 'mr00003'), ('会员名', 'mrkj')])
使用DictReader 类读取csv 文件指定列数据,如“订单编号”和“会员名”列,代码如下:
import csv
with open(‘test_csv_data.csv’,’r’) as f:
reader = csv.DictReader(f)
for row in reader:
print(row[‘订单编号'], row[‘会员名'])
程序运行结果如下:
mr00001 mrsoft
mr00002 mingri
mr00003 mrkj
使用DictReader 类读取csv 文件某一行数据,可以通过指定列的标题查询。例如,查询“订单编号”为“mr00001”的数据,代如下:
import csv
with open(‘test_csv_data.csv’,’r’) as f:
reader = csv.DictReader(f)
for row in reader:
if row[‘订单编号']==’mr00001’:
print(row)
程序运行结果如下:
OrderedDict([('订单编号', 'mr00001'), ('会员名', 'mrsoft')])
以字典方式读取csv 文件,首先创建字典,然后按行读取并存入字典,代码如下:
import csv
dictreader = csv.DictReader(open(‘test_csv_data.csv’,newline=’’), delimiter=’,’)
dictdata = {} # 创建字典
i=0
for row in dictreader:
dictdata[i]=row # 写入字典
i=i+1
print(dictdata)
程序运行结果如下:
{0: OrderedDict([('订单编号', 'mr00001'), ('会员名', 'mrsoft')]), 1: OrderedDict([('订单编号', 'mr00002'), ('会员名', 'mingri')]), 2: OrderedDict([('订单编号', 'mr00003'), ('会员名','mrkj')])}
有些时候,我们需要从csv 文件中获取符合查询条件的数据,而不是全部数据。这时,可以通过re 模块提供的正则表达式来理。例如,查询eat.csv 文件中“商家名称”中包含“麻辣烫”的数据,代码如下:
import csv
import re
with open(‘eat.csv’,’r’) as f:
reader = csv.DictReader(f)
value=’麻辣烫' # 关键字“麻辣烫”
pattern = ‘.*’ + value + ‘.*’ # 模糊匹配
for row in reader:
data = re.findall(pattern, row[‘商家名称']) # 查询数据
if len(data)>0:
print(row[‘序号'],row[‘商家名称'])
程序运行结果如下:
老字号正宗四川麻辣烫店
美香居砂锅麻辣烫米线
箐山砂锅麻辣烫
一麻一辣麻辣烫(万豪店)
张亮麻辣烫(万科杨浦花园店)
DictWriter 类用于创建一个支持字典类型的csv 文件。语法格式如下:
csv.DictWriter(f,fieldnames,restval='',extrasaction='raise',dialect='excel',*args,**kwds)
参数说明:
f :表示文件对象。
fieldnames:表示字段名称,该参数不是可选的。
restval:如果csv文件中缺少指定的字段名,则使用可选参数restval指定要写入的值。
extrasaction:如果传递给方法的字典包含字段名中找不到的键,则使用可选参数extrasaction指定要采取的操作。
dialect:支持excel格式的csv编码风格。
args :不定数量的非键值对参数(格式参数)。
**kwds:不定数量的键值对参数(格式参数)。
返回值:返回csv文件。
注意:DictWriter 类与DictReader 类不同,DictWriter 类的fieldnames 参数不是可选的。
使用DictWriter 类将字典数据写入csv 文件中,代码如下:
import csv
with open(‘mrdata.csv’,’w’,newline=’’)as csvfile:
fieldnames=[‘运单号',’目的地',’客户运费']
writer=csv.DictWriter(csvfile,fieldnames=fieldnames)
writer.writeheader()
writer.writerow({‘运单号':’800123’,’目的地':’长春',’客户运费':4})
writer.writerow({‘运单号':’800124’,’目的地':’吉林',’客户运费':5})
writer.writerow({‘运单号':’800125’,’目的地':’四平',’客户运费':5})
DictWriter 类的writeheader 方法用于将字段名称作为一行数据写入csv 文件中。语法格式如下:
DictWriter.writeheader()
参数说明:
使用writeheader() 方法为csv 文件写入表头,代码如下:
import csv
csvFile = open(‘csv_h1.csv’, ‘w’,newline=’’)
fileheader = [‘订单编号',’会员名',’商品名称']
dict_writer = csv.DictWriter(csvFile, fileheader) # 写入标题
dict_writer.writeheader()
dict_writer.writerow({‘订单编号': ‘mr00001’, ‘会员名': ‘mrsoft’, ‘商品名称': ‘零基础学Python’})
csvFile.close()
在excel 类中定义生成csv 文件的excel 格式,csv 文件的编码风格为excel。语法格式如下:
csv.excel
参数说明:
通过excel 类定义支持excel 格式的csv 文件。该格式为csv 文件常见的格式,默认以逗号作为分隔符,代码如下:
import csv
# 定义excel类
class mydialect(csv.excel):
dialect=’excel’
# 写入文件
with open(‘mrsoft2.tsv’, ‘w’, newline=’’) as csvfile:
spamwriter = csv.writer(csvfile,mydialect)
spamwriter.writerow([‘mrkj’] * 5 + [‘www.mingrisoft.com’])
spamwriter.writerow([‘mrkj’, ‘4006751066’, ‘0431-84978981’])
# 读取文件
with open(‘mrsoft2.tsv’) as myFile: # 打开csv文件
rows=csv.reader(myFile) # 读取csv文件
for row in rows: # 按行读取
print(‘,’.join(row))
iterow([‘mrkj’, ‘4006751066’, ‘0431-84978981’])
创建csv 文件,在excel 类中定义excel 格式并使用分号作为分隔符,代码如下:
import csv
# 定义excel类
class mri(csv.excel):
delimiter = ‘;’
dialect=’excel’
csv.register_dialect(‘mri’) # 注册csv编码风格mri
# 写入文件
with open(‘mrbooks.mri’,’w’,newline=’’) as myFile: # 打开文件
writer = csv.writer(myFile, mri)
writer.writerow([‘运单号',’目的地'])
writer.writerow([‘0001’, ‘长春'])
excel_tab 类用于定义Excel 生成的由制表符分隔的文件格式,csv 文件的编码风格为excel-tab。语法格式如下:
csv.excel_tab
参数说明:
csv 文件默认是用逗号分隔的,但是有些环境可能需要csv 文件是用制表符分隔的,读取时也只识别制表符,那么此时可以通过excel_tab 类来定义这种以制表符为分隔符的csv 文件格式,代码如下:
import csv
# 定义excel-tab类
class mytab(csv.excel_tab):
dialect=’excel-tab’
# 写入文件
with open(‘mrsoft2.tsv’, ‘w’, newline=’’) as csvfile:
spamwriter = csv.writer(csvfile,mytab)
spamwriter.writerow([‘mrkj’] * 5 + [‘www.mingrisoft.com’])
spamwriter.writerow([‘mrkj’, ‘4006751066’, ‘0431-84978981’])
# 读取文件
with open(‘mrsoft2.tsv’) as myFile: # 打开csv文件
rows=csv.reader(myFile) # 读取csv文件
for row in rows: # 按行读取
print(‘,’.join(row))
Sniffer 类用于检测csv 文件的编码风格。语法格式如下:
csv.Sniffer
参数说明:
返回值:返回一个Dialect实例,其中包含用于解析数据的设置。
Sniffer 类提供了两个方法:
Ø sniff() 方法:分析给定的文件并返回Dialect 实例。如果给出了可选的delimiters 参数,则将其解释为包含可能的有效分隔符的字符串。
Ø has_header() 方法:分析示例文本(如csv 文件),如果第一行显示为一系列列标题,则返回True。
首先注册两个新的编码风格,然后写入数据至缓存,再通过Sniffer 类检测编码风格并对不同编码风格的数据进行解析,代码如下:
import csv
from io import StringIO
import textwrap
# 注册新的编码风格
csv.register_dialect(‘escaped’,
escapechar=’\\’,
doublequote=False,
quoting=csv.QUOTE_NONE)
csv.register_dialect(‘singlequote’,
quotechar=”’”,
quoting=csv.QUOTE_ALL)
# 以不同的编码风格写入csv文件
data = []
for name in sorted(csv.list_dialects()):
# 数据写入缓存
buffer = StringIO()
dialect = csv.get_dialect(name)
writer = csv.writer(buffer, dialect=dialect)
writer.writerow((‘公司', 1, ‘2019-09-05’,’吉林省明日科技有限公司'))
data.append((name, dialect, buffer.getvalue()))
# 检测编码风格,解析数据
sniffer = csv.Sniffer()
for name, expected, sample in data:
print(‘编码风格: “{}”’.format(name))
print(‘原数据: {}’.format(sample.rstrip()))
dialect = sniffer.sniff(sample, delimiters=’,\t’)
reader = csv.reader(StringIO(sample), dialect=dialect)
print(‘解析数据:\n {}\n’.format(‘\n ‘.join(repr(r) for r in next(reader))))
u nix_dialect 类用于定义适合在UNIX 系统上使用的csv 文件,其文件的编码风格为unix。语法格式如下:
csv.unix_dialect
参数说明:
使用unix_dialect 类定义UNIX 系统的csv 文件,代码如下:
import csv
# 定义excel类
class mydialect(csv.unix_dialect):
dialect=’unix’
# 写入文件
with open(‘mrsoft2.usv’, ‘w’, newline=’’) as csvfile:
spamwriter = csv.writer(csvfile,mydialect)
spamwriter.writerow([‘mrkj’] * 5 + [‘www.mingrisoft.com’])
spamwriter.writerow([‘mrkj’, ‘4006751066’, ‘0431-84978981’])
# 读取文件
with open(‘mrsoft2.usv’) as myFile: # 打开文件
rows=csv.reader(myFile) # 读取文件
for row in rows: # 按行读取
print(‘,’.join(row))
程序运行结果如下:
mrkj,mrkj,mrkj,mrkj,mrkj,www.mingrisoft.com
mrkj,4006751066,0431-84978981
说明:为了区分Windows 系统中的csv 文件,我们将UNIX 系统中csv 文件的文件扩展名命名为.usv。
reader 对象的fieldnames 属性用于读取csv 文件中字段的名称。语法格式如下:
reader.fieldnames
参数说明:
使用fieldnames 属性读取csv 文件的表头字段名称,代码如下:
import csv
with open('mrdata.csv')as csvfile:
reader = csv.DictReader(csvfile)
head = reader.fieldnames
print(head)
程序运行结果如下:
['运单号', '账单日期', '结算对象', '目的地', '城市', '结算重量', '派件网点', '签收网点', '签收时间', '客
户运费']
先使用fieldnames 属性读取csv 文件的表头字段,然后再按照表头字段读取某列数据,如第0 列“运单号”列,代码如下:
import csv
with open(‘mrdata.csv’) as csvfile:
reader = csv.DictReader(csvfile)
# 读取文件的表头字段信息
head = reader.fieldnames
for row in reader:
# 按表头字段信息读取第0列数据
col1 = row[head[0]]
print(col1)
程序运行结果如下:
7515123
7515124
7515125
7515126
7515127
7515128
7515129
7515130
首先使用fieldnames 属性读取csv 文件的表头字段,然后按照表头字段读取某列数据,如第0 列“运单号”列,最后通过列表的append() 方法将“运单号”保存到列表中,代码如下:
import csv
with open(‘mrdata.csv’) as f:
reader = csv.DictReader(f)
data = []
# 获取csv文件的表头字段
head = reader.fieldnames
for row in reader:
# 按表头信息提取第0列数据
col1 = row[head[0]]
# 将第0列数据转换成字符串保存到列表中
data.append(‘‘.join(col1))
print(data)
程序运行结果如下:
['7515123', '7515124', '7515125', '7515126', '7515127', '7515128', '7515129', '7515130']
lreader 对象的ine_num 属性用于返回csv 文件的行号。语法格式如下:
reader.line_num
参数说明:
读取csv 文件中的数据时,有时候为了处理数据方便而不需要表头,这种情况下可以使用line_num 属性跳过第一行不读取表头,代码如下:
import csv
with open(‘mrdata.csv’) as csvfile:
reader=csv.reader(csvfile)
for row in reader:
# 忽略第一行
if reader.line_num == 1:
continue
print(row)
使用line_num 属性读取csv 文件的行号,代码如下:
import csv
with open(‘mrdata.csv’) as csvfile:
reader=csv.reader(csvfile)
for row in reader:
print(‘行号:',reader.line_num) # 读取行号
reader 对象的__next__() 方法用于读取csv 文件中的下一行数据。语法格式如下:
reader.__next__()
参数说明:
使用__next__() 方法读取csv 文件中的数据的下一行,代码如下:
import csv
# 写入数据
with open(‘b1.csv’, ‘w’, newline=’’) as csvfile:
w = csv.writer(csvfile, delimiter=’ ‘,quoting=csv.QUOTE_NONE,escapechar=’$’,quotechar=’|’,skipinitialspace=False)
w.writerow([‘mrkj’] * 5 + [‘www.mingrisoft.com’])
w.writerow([‘mrkj’, 4006751066, 84978981])
# 读取数据
with open(‘b1.csv’,’r’) as f:
reader = csv.reader(f)
print(reader.__next__())
程序运行结果如下:
['mrkj mrkj mrkj mrkj mrkj www.mingrisoft.com']
有时程序需要按行读取csv 文件中的数据。例如,当用户单击“下一行”按钮时,输出该行数据。首先,使用tkinter 模块制作按钮,编写鼠标单击事件,然后使用__next__() 方法读取csv 文件中的数据的下一行,代码如下:
import csv
from tkinter import *
root=Tk()
root.title(‘读取csv文件数据')
# 单击按钮读取数据
with open(‘r1.csv’,’r’) as f:
reader = csv.reader(f)
# 定义读取下一行数据的函数rnext()
def rnext():
print(reader.__next__())
# 设置按钮
b=Button(root,text=’下一行',font=(‘KaiTi’,36,’bold’),bg=’pink’,fg=’green’,bd=2,
width=10,command=rnext)
b.pack()
root.mainloop()
writer 对象的writerow() 方法用于写一行数据到csv 文件中。语法格式如下:
writer.writerow(row)
参数说明:
row :列表类型,表示写入csv文件的字符串。
返回值:无。
使用writerow() 方法向csv 文件写入一行数据,代码如下:
import csv
with open(‘csv_test1.csv’, ‘w’,newline=’’) as f: # 如不指定newline=’’,有时会写入空行
writer = csv.writer(f)
writer.writerow([‘订单编号', ‘会员名', ‘商品名称']) # 写入一行标题
writerow() 方法不仅可以写入单行数据,数据较少的情况下也可以写入多行。例如,写入3 行订单数据,代码如下:
import csv
with open(‘csv_test1.csv’, ‘w’,newline=’’) as f: # 如不指定newline=’’,有时会写入空行
writer = csv.writer(f)
writer.writerow([‘订单编号', ‘会员名', ‘商品名称']) # 写入一行标题
writer.writerow([‘mr00001’,’mrsoft’,’零基础学Python’]) # 写入一行数据
writer.writerow([‘mr00002’,’mingri’,’Python从入门到项目实践']) # 写入一行数据
writer.writerow([‘mr00003’,’mrkj’,’Python编程锦囊']) # 写入一行数据
在向csv 文件写入数据时,有时会写入空行。解决这一问题,需要在创建文件时,设置参数newline=‘’(注:这里是两个单引号),代码如下:
import csv
with open(‘csv_test3.csv’, ‘w’,newline=’’) as f: # 如不指定newline=’’,会写入空行
writer = csv.writer(f)
writer.writerow([‘订单编号', ‘会员名', ‘商品名称']) # 写入一行标题
writer.writerow([‘mr00001’,’mrsoft’,’零基础学Python’]) # 写入一行数据
writer.writerow([‘mr00002’,’mingri’,’Python从入门到项目实践']) # 写入一行数据
writer.writerow([‘mr00003’,’mrkj’,’Python编程锦囊']) # 写入一行数据
使用writerow() 方法结合循环语句,实现以字典方式向csv 文件写入多行数据,代码如下:
import csv
datas = [{‘订单编号':’mr00001’,’会员名':’mrsoft’},{‘订单编号':’mr00002’,’会员名':’mingri’},{‘订单编号':’mr00003’,’会员名':’mrkj’}]
with open(‘csv_test4.csv’, ‘w’, newline=’’) as f:
writer = csv.DictWriter(f, [‘订单编号', ‘会员名']) # 写入表头,第一行数据
writer.writeheader()
for row in datas: # 写入多行数据
writer.writerow(row)
用户通过Python 录入表格数据,然后生成csv 文件。首先,通过input() 函数录入相关数据,然后使用writerow() 方法将录入的数据写入到csv 文件中,代码如下:
import csv
def read(file1):
with open(file1, ‘r+’, newline=’’) as csv_file:
reader = csv.reader(csv_file)
return [row for row in reader]
def write(file1, rows):
with open(file1, ‘w+’, newline=’’) as csv_file:
writer = csv.writer(csv_file)
for row in rows:
writer.writerow(row)
def entering_data():
cols = int(input(“请输入录入列数(整数):"))
input_rows = []
gogo = True
while gogo:
input_rows.append([input(“列名 {}: “.format(i + 1)) for i in range(0, cols)])
a = input(“是否继续录入数据? (y/N): “)
if a != “y”:
gogo = False
write(‘w5.csv’, input_rows)
written_value = read(‘w5.csv’)
print(str(written_value))
entering_data()
使用writerow() 方法写入超长数字时,如图书的ISBN 号,写入完成再次打开csv 文件,ISBN都显示成了科学记数法,解决这个问题,需要在保存的数字后加上“‘\t’”,代码如下:
import csv
with open(‘isbn.csv’, ‘w’,newline=’’) as f: # 指定newline=’’,防止写入空行
writer = csv.writer(f)
writer.writerow([‘ISBN’])
writer.writerow([‘9787567787421’+’\t’])
writer.writerow([‘9787569208542’+’\t’])
writer.writerow([‘9787569204537’+’\t’])
通过循环语句结合随机函数批量生成学生信息,如ID、学号和班级,然后循环写入csv 文件,代码如下:
import csv
import random
j=0
ID=0
csvname = input(‘请输入文件名:’)
out = csv.writer(open(csvname + ‘.csv’,’w’, newline=’’))
out.writerow([‘ID’, ‘学号', ‘班级']) # 写入表头
while j<5:
for i in range(9):
num=random.randint(20190000,20199999) # 随机生成“学号”
Student=str(num)
Grade=’高一十二班'
ID+=1
out = csv.writer(open(csvname + ‘.csv’,’a+’, newline=’’))
out.writerow([ID,Student,Grade]) # 写入学生数据
j+=1
writer 对象的writerows() 方法用于将行中的所有元素(行对象的可迭代数据)写入到csv 文件。语法格式如下:
writer.writerows(data)
参数说明:
data :表示可迭代数据。
返回值:无。
首先打开一个csv 文件,通过writerow() 方法写入csv 文件的表头,然后使用writerows() 方法写入多行数据到csv 文件中,代码如下:
import csv
with open(‘csv_rows.csv’, ‘w’,newline=’’) as f: # 指定newline=’’,防止写入空行
writer = csv.writer(f)
writer.writerow([‘订单编号’, ‘会员名’, ‘商品名称’]) # 写入一行表头
data = [(‘mr00001’,’mrsoft’,’零基础学Python’),(‘mr00002’,’mingri’,’Python从入门到项目实践’),(‘mr00003’,’mrkj’,’Python编程锦囊’)]
writer.writerows(data) # 写入多行数据
使用writerows() 方法以字典方式向csv 文件写入多行数据,代码如下:
import csv
datas = [{‘订单编号':’mr00001’,’会员名':’mrsoft’},{‘订单编号':’mr00002’,’会员名':’mingri’},{‘订单编号':’mr00003’,’会员名':’mrkj’}]
with open(‘csv_rows.csv’, ‘w’, newline=’’) as f:
writer = csv.DictWriter(f, [‘订单编号', ‘会员名']) # 写入表头,第一行数据
writer.writeheader()
# 写入多行
writer.writerows(datas)
将列表中的数据通过writerows() 方法保存到csv 文件中,代码如下:
import csv
data=[[‘西施',’法师',’2019.09.24’],[‘马超',’战士',’2019.08.15’],[‘曜',’战士',’2019.06.27’]]
h=[“新英雄",”类别",”上线时间"]
with open(“王者荣耀.csv”,’w’,newline=’’) as f:
writer=csv.writer(f)
writer.writerow(h) # 写入表头
writer.writerows(data) # 写入数据