我心中的王者:Python-第20章 使用Python处理CSV文件
CSV是一个缩写,它的英文全名是Comma-Separated Values,由字面意义可以解说是逗号分隔值,当然逗号是主要数据字段间的分隔值,不过目前也有非逗号的分隔值。这是一个纯文本格式的文件,没有图片、不用考虑字体、大小、颜色等。
简单地说,CSV数据是指同一行(row)的资料彼此用逗号(或其他符号)隔开,同时每一行数据数据是一笔(record)数据,几乎所有电子表格与数据库文件均支持这个文件格式。
20-1 建立一个CSV文件
为了更详细解说,笔者先用ch20文件夹的report.xlsx文件产生一个CSV文件,未来再用这个文件做说明。目前窗口内容是report.xlsx,如下所示:
请执行另存为命令,然后选择目前D:\Python\ch20文件夹。存档类型选CSV(逗号分隔)(*.csv),然后将文件名改为csvReport。
点击保存按钮后,出现下列信息。
请单击是按钮,可以得到下列结果。
我们已经成功地建立一个CSV文件了,文件是csvReport.csv,可以关闭上述Excel窗口了。
20-2 用记事本打开CSV文件
CSV文件的特色是几乎可以在所有不同的电子表格内编辑,当然也可以在一般的文字编辑程序内查阅使用,如果我们现在使用记事本打开这个CSV文件,可以看到这个文件的原貌。
20-3 CSV模块
Python有内置CSV模块,导入这个模块后,可以很轻松读取CSV文件,方便未来程序的操作,所以本章程序前端要加上下列指令。
import csv
20-4 读取CSV文件
20-4-1 使用open( )打开CSV文件
在读取CSV文件前第一步是使用open( )打开文件,语法格式如下:
with open(文件名) as csvFile # csvFile是可以自行命名的文件对象
相关系列指令
如果忘了with关键词的用法,可以参考14-2-2小节。当然你也可以直接使用传统方法打开文件。
csvFile = open(文件名) # 打开文件建立CSV文件对象csvFile
20-4-2 建立Reader对象
有了CSV文件对象后,下一步可以使用csv模块的reader( )建立Reader对象,可以使用list( )将这个Reader对象转换成列表(list),现在我们可以很轻松地使用这个列表资料了。
程序实例ch20_1.py:打开csvReport.csv文件,读取csv文件可以建立Reader对象csvReader,再将csvReader对象转成列表数据,然后打印列表数据。
# ch20_1.py
import csv
fn = 'csvReport.csv'
with open(fn) as csvFile: # 开启csv档案
csvReader = csv.reader(csvFile) # 读档案建立Reader对象
listReport = list(csvReader) # 将数据转成列表
print(listReport) # 打印列表方法
执行结果
[['Name', 'Year', 'Product', 'Price', 'Quantity', 'Revenue', 'Location'], ['Diana', '2015', 'Black Tea', '10', '600', '6000', 'New York'], ['Diana', '2015', 'Green Tea', '7', '660', '4620', 'New York'], ['Diana', '2016', 'Black Tea', '10', '750', '7500', 'New York'], ['Diana', '2016', 'Green Tea', '7', '900', '6300', 'New York'], ['Julia', '2015', 'Black Tea', '10', '1200', '12000', 'New York'], ['Julia', '2016', 'Black Tea', '10', '1260', '12600', 'New York'], ['Steve', '2015', 'Black Tea', '10', '1170', '11700', 'Chicago'], ['Steve', '2015', 'Green Tea', '7', '1260', '8820', 'Chicago'], ['Steve', '2016', 'Black Tea', '10', '1350', '13500', 'Chicago'], ['Steve', '2016', 'Green Tea', '7', '1440', '10080', 'Chicago']]
上述程序需留意的是,程序第6行所建立的Reader对象csvReader,只能在with关键区块内使用,此例是5-7行,未来我们要继续操作这个CSV文件内容,需使用第7行所建的列表listReport或是重新开档与读档。
20-4-3 用循环列出Reader对象数据
我们可以使用for循环操作Reader对象,列出各行数据,同时使用Reader对象的line_num属性列出行号。
程序实例ch20_2.py:读取Reader对象,然后以循环方式列出对象内容。
# ch20_2.py
import csv
fn = 'csvReport.csv'
with open(fn) as csvFile: # 开启csv档案
csvReader = csv.reader(csvFile) # 读档案建立Reader对象csvReader
for row in csvReader: # 用循环列出csvReader对象内容
print("Row %s = " % csvReader.line_num, row)
执行结果
Row 1 = ['Name', 'Year', 'Product', 'Price', 'Quantity', 'Revenue', 'Location']
Row 2 = ['Diana', '2015', 'Black Tea', '10', '600', '6000', 'New York']
Row 3 = ['Diana', '2015', 'Green Tea', '7', '660', '4620', 'New York']
Row 4 = ['Diana', '2016', 'Black Tea', '10', '750', '7500', 'New York']
Row 5 = ['Diana', '2016', 'Green Tea', '7', '900', '6300', 'New York']
Row 6 = ['Julia', '2015', 'Black Tea', '10', '1200', '12000', 'New York']
Row 7 = ['Julia', '2016', 'Black Tea', '10', '1260', '12600', 'New York']
Row 8 = ['Steve', '2015', 'Black Tea', '10', '1170', '11700', 'Chicago']
Row 9 = ['Steve', '2015', 'Green Tea', '7', '1260', '8820', 'Chicago']
Row 10 = ['Steve', '2016', 'Black Tea', '10', '1350', '13500', 'Chicago']
Row 11 = ['Steve', '2016', 'Green Tea', '7', '1440', '10080', 'Chicago']
20-4-4 用循环列出列表内容
for循环也可用于列出列表内容。
程序实例ch20_3.py:用for循环列出列表内容。
# ch20_3.py
import csv
fn = 'csvReport.csv'
with open(fn) as csvFile: # 开启csv档案
csvReader = csv.reader(csvFile) # 读档案建立Reader对象
listReport = list(csvReader) # 将数据转成列表
for row in listReport: # 使用循环列出列表内容
print(row)
执行结果
['Name', 'Year', 'Product', 'Price', 'Quantity', 'Revenue', 'Location']
['Diana', '2015', 'Black Tea', '10', '600', '6000', 'New York']
['Diana', '2015', 'Green Tea', '7', '660', '4620', 'New York']
['Diana', '2016', 'Black Tea', '10', '750', '7500', 'New York']
['Diana', '2016', 'Green Tea', '7', '900', '6300', 'New York']
['Julia', '2015', 'Black Tea', '10', '1200', '12000', 'New York']
['Julia', '2016', 'Black Tea', '10', '1260', '12600', 'New York']
['Steve', '2015', 'Black Tea', '10', '1170', '11700', 'Chicago']
['Steve', '2015', 'Green Tea', '7', '1260', '8820', 'Chicago']
['Steve', '2016', 'Black Tea', '10', '1350', '13500', 'Chicago']
['Steve', '2016', 'Green Tea', '7', '1440', '10080', 'Chicago']
20-4-5 使用列表索引读取CSV内容
其实我们也可以使用第6章所学的列表知识,读取CSV内容。
程序实例ch20_4.py:使用索引列出列表内容。
# ch20_4.py
import csv
fn = 'csvReport.csv'
with open(fn) as csvFile: # 开启csv档案
csvReader = csv.reader(csvFile) # 读档案建立Reader对象
listReport = list(csvReader) # 将数据转成列表
print(listReport[0][1], listReport[0][2])
print(listReport[1][2], listReport[1][5])
print(listReport[2][3], listReport[2][6])
执行结果
Year Product
Black Tea 6000
7 New York
20-4-6 DictReader( )
这也是一个读取CSV文件的方法,不过传回的是排序字典 (OrderedDict) 类型,所以可以用域名当索引方式取得数据。在美国许多文件以CSV文件储存时,常常人名的Last Name(姓)与First Name(名)是分开以不同字段储存,读取时可以使用这个方法,可参考ch20文件夹的csvPeople.csv文件。
程序实例ch20_5.py:使用DictReader( )读取csv文件,然后列出DictReader对象内容。
# ch20_5.py
import csv
fn = 'csvPeople.csv'
with open(fn) as csvFile: # 开启csv档案
csvDictReader = csv.DictReader(csvFile) # 读档案建立DictReader对象
for row in csvDictReader: # 列出DictReader各行内容
print(row)
执行结果
{'first_name': 'Eli', 'last_name': 'Manning', 'city': 'New York'}
{'first_name': 'Kevin ', 'last_name': 'James', 'city': 'Cleveland'}
{'first_name': 'Mike', 'last_name': 'Jordon', 'city': 'Chicago'}
对于上述OrderedDict数据类型,可以使用下列方法读取。
程序实例ch20_6.py:将csvPeople.csv文件的last_name与first_name解析出来。
# ch20_6.py
import csv
fn = 'csvPeople.csv'
with open(fn) as csvFile: # 开启csv档案
csvDictReader = csv.DictReader(csvFile) # 读档案建立DictReader对象
for row in csvDictReader: # 使用循环列出字典内容
print(row['first_name'], row['last_name'])
执行结果
Eli Manning
Kevin James
Mike Jordon
20-5 写入CSV文件
20-5-1 打开欲写入的文件open( )与关闭文件close( )
想要将数据写入CSV文件,首先是要打开一个文件供写入,如下所示:
当然如果使用with关键词可以省略close( ),如下所示:
20-5-2 建立writer对象
如果应用前一节的csvFile对象,接下来需建立writer对象,语法如下:
或是
上述打开文件时多加参数newline=‘ ’,可避免输出时每个行之间多空一行。
20-5-3 输出列表writerow( )
writerow( )可以输出列表数据。
程序实例ch20_7.py:输出列表数据的应用。
# ch20_7.py
import csv
fn = 'out20_7.csv'
with open(fn, 'w', newline = '') as csvFile: # 开启csv档案
csvWriter = csv.writer(csvFile) # 建立Writer对象
csvWriter.writerow(['Name', 'Age', 'City'])
csvWriter.writerow(['Hung', '35', 'Taipei'])
csvWriter.writerow(['James', '40', 'Chicago'])
执行结果 下列是分别用记事本与Excel打开文件的结果。
本书在ch20文件夹内有ch20_7_1.py文件,这个文件在第5行open( )中没有加上newline=‘’,造成输出时若用Excel窗口观察有跳行输出的现象,可参考out20_7_1.csv文件,至于用记事本打开文件则一切正常,下列是程序代码。
下列是执行结果,读者可以比较下图右边的Excel报表。
程序实例ch20_8.py:复制CSV文件,这个程序会用读文件,然后将文件写入另一个文件的方式,达成复制的目的。
# ch20_8.py
import csv
infn = 'csvReport.csv' # 来源档案
outfn = 'out20_8.csv' # 目标文件
with open(infn) as csvRFile: # 开启csv档案供读取
csvReader = csv.reader(csvRFile) # 读档案建立Reader对象
listReport = list(csvReader) # 将数据转成列表
with open(outfn, 'w', newline = '') as csvOFile: # 开启csv档案供写入
csvWriter = csv.writer(csvOFile) # 建立Writer对象
for row in listReport: # 将列表写入
csvWriter.writerow(row)
执行结果 读者可以打开out20_8.csv文件,内容将和csvReport.csv文件相同。
20-5-4 delimiter关键词
delimiter是分隔符,这个关键词是用在writer( )方法内,将数据写入CSV文件时预设是同一行各栏间是逗号,可以用这个分隔符更改各栏间的逗号。
程序实例ch20_9.py:将分隔符改为定位点字符(\t)。
# ch20_9.py
import csv
fn = 'out20_9.csv'
with open(fn, 'w', newline = '') as csvFile: # 开启csv档案
csvWriter = csv.writer(csvFile, delimiter='\t') # 建立Writer对象
csvWriter.writerow(['Name', 'Age', 'City'])
csvWriter.writerow(['Hung', '35', 'Taipei'])
csvWriter.writerow(['James', '40', 'Chicago'])
执行结果 下列是用记事本打开out20_9.csv的结果。
当用‘\t’字符取代逗号后,Excel窗口打开这个文件时,会将每行数据挤在一起,所以最好方式是用记事本打开这类的CSV文件。
20-5-5 写入字典数据DictWriter( )
DictWriter( )可以写入字典数据,其语法格式如下:
dictWriter = csv.DictWriter(csvFile,fieldnames=fields)
上述dictWriter是字典的Writer对象,在上述指令前我们需要先设定fields列表,这个列表将包含未来字典内容的键(key)。
程序实例ch20_10.py:使用DictWriter( )将字典数据写入CSV文件。
# ch20_10.py
import csv
fn = 'out20_10.csv'
with open(fn, 'w', newline = '') as csvFile: # 开启csv档案
fields = ['Name', 'Age', 'City']
dictWriter = csv.DictWriter(csvFile, fieldnames=fields) # 建立Writer对象
dictWriter.writeheader() # 写入标题
dictWriter.writerow({'Name':'Hung', 'Age':'35', 'City':'Taipei'})
dictWriter.writerow({'Name':'James', 'Age':'40', 'City':'Chicago'})
执行结果 下列是用Excel打开out20_10.csv的结果。
上述程序第9行的writeheader( )主要是写入我们在第7行设定的fieldname。
程序实例ch20_11.py:改写程序实例ch20_10.py,将欲写入CSV文件的数据改成列表数据,此列表数据的元素是字典。
# ch20_11.py
import csv
dictList = [{'Name':'Hung', 'Age':'35', 'City':'Taipei'}, # 定义列表,元素是字典
{'Name':'James', 'Age':'40', 'City':'Chicago'}]
fn = 'out20_11.csv'
with open(fn, 'w', newline = '') as csvFile: # 开启csv档案
fields = ['Name', 'Age', 'City']
dictWriter = csv.DictWriter(csvFile, fieldnames=fields) # 建立Writer对象
dictWriter.writeheader() # 写入标题
for row in dictList: # 写入内容
dictWriter.writerow(row)
执行结果 打开out20_11.csv后与out20_1 0.csv相同。
20-6 后记
读者可能会想学习了打开个别CSV文件的用处在哪里?现在是大数据时代,所有数据搜集无法完整地用某一种格式呈现,CSV是电子表格和数据库间最常用的资料格式,我们可以先将所搜集的各式文件转成CSV,然后你就可以使用Python读取所有的CSV文件,再提取需要的数据做大数据分析。或是利用CSV文件,将它当作不同数据库间的桥梁或数据库与电子表格间的桥梁。