Python使用csv模块读写CSV文件的完整指南
本文详细介绍Python中如何使用内置csv模块高效读写CSV文件。内容涵盖基础读写、使用命名元组和字典简化字段访问、处理特殊分隔符及编码,以及手动类型转换和错误处理机制,最后推荐Pandas用于高级数据分析。
Python CSV读写基础
问题
你需要处理CSV格式文件的读写操作。
解决方案
针对大多数CSV数据的读写需求,推荐使用Python内置的csv库。假设你有一个名为stocks.csv的文件,其中包含股票市场数据,格式如下:
读取CSV数据
接下来展示如何将这些数据读取为元组序列:
import csv
with open('stocks.csv') as f:
f_csv = csv.reader(f)
headers = next(f_csv)
for row in f_csv:
# Process row
...
在上述代码中,row 代表每一行数据,它是一个元组。因此,要访问特定字段,需使用索引,例如通过row[0]获取Symbol,通过row[4]获取Change。
使用命名元组简化访问
由于索引访问容易混淆,建议使用命名元组(namedtuple)。示例如下:
from collections import namedtuple
with open('stock.csv') as f:
f_csv = csv.reader(f)
headings = next(f_csv)
Row = namedtuple('Row', headings)
for r in f_csv:
row = Row(*r)
# Process row
...
这种方式允许你通过列名如row.Symbol和row.Change直接访问数据,而非使用索引。需要注意的是,这要求列名必须是合法的Python标识符。若列名包含非法字符,需先对原始列名进行修改,例如将特殊字符替换为下划线。
使用字典序列访问
另一种选择是将数据读取为字典序列,实现方式如下:
import csv
with open('stocks.csv') as f:
f_csv = csv.DictReader(f)
for row in f_csv:
# process row
...
在此版本中,你可以直接使用列名访问每行数据,例如row['Symbol']或row['Change']。
写入CSV数据
写入CSV数据时,同样使用csv模块,但需先创建一个writer对象。例如:
headers = ['Symbol','Price','Date','Time','Change','Volume']
rows = [('AA', 39.48, '6/11/2007', '9:36am', -0.18, 181800),
('AIG', 71.38, '6/11/2007', '9:36am', -0.15, 195500),
('AXP', 62.58, '6/11/2007', '9:36am', -0.46, 935000),
]
with open('stocks.csv','w') as f:
f_csv = csv.writer(f)
f_csv.writerow(headers)
f_csv.writerows(rows)
若数据为字典序列,可按如下方式写入:
headers = ['Symbol', 'Price', 'Date', 'Time', 'Change', 'Volume']
rows = [{'Symbol':'AA', 'Price':39.48, 'Date':'6/11/2007',
'Time':'9:36am', 'Change':-0.18, 'Volume':181800},
{'Symbol':'AIG', 'Price': 71.38, 'Date':'6/11/2007',
'Time':'9:36am', 'Change':-0.15, 'Volume': 195500},
{'Symbol':'AXP', 'Price': 62.58, 'Date':'6/11/2007',
'Time':'9:36am', 'Change':-0.46, 'Volume': 935000},
]
with open('stocks.csv','w') as f:
f_csv = csv.DictWriter(f, headers)
f_csv.writeheader()
f_csv.writerows(rows)
CSV模块深入讨论
讨论
避免手动解析
建议始终优先使用csv模块来分割或解析CSV数据。例如,有人可能编写如下代码:
with open('stocks.csv') as f:
for line in f:
row = line.split(',')
# process row
...
这种方式存在缺点,仍需手动处理棘手细节。例如,若字段值被引号包围,需去除引号;若被引号包围的字段内含逗号,程序可能因解析出行大小错误而报错。
处理不同编码与分隔符
默认情况下,csv库识别Microsoft Excel使用的CSV编码规则,这是最常见且兼容性最好的形式。查看csv文档可知,有多种方法可应用于其他编码格式(如修改分隔符)。例如,读取以Tab分隔的数据可如下操作:
# Example of reading tab-separated values
with open('stock.tsv') as f:
f_tsv = csv.reader(f, delimiter='\t')
for row in f_tsv:
# Process row
...
列名合法性验证
若读取CSV数据并转换为命名元组,需注意列名的合法性验证。例如,若CSV文件包含非法标识符的列头,如下所示:
这会导致创建命名元组时抛出ValueError异常。解决方法是预先修正列标题,例如使用正则表达式替换非法标识符:
import re
with open('stock.csv') as f:
f_csv = csv.reader(f)
headers = [ re.sub('[^a-zA-Z_]', '_', h) for h in next(f_csv) ]
Row = namedtuple('Row', headers)
for r in f_csv:
row = Row(*r)
# Process row
...
数据类型转换
此外需强调,csv生成的数据均为字符串类型,不进行其他类型转换。如需类型转换,必须手动实现。以下示例展示如何在CSV数据上执行类型转换:
col_types = [str, float, str, str, float, int]
with open('stocks.csv') as f:
f_csv = csv.reader(f)
headers = next(f_csv)
for row in f_csv:
# Apply conversions to the row items
row = tuple(convert(value) for convert, value in zip(col_types, row))
...
另外,以下示例展示如何转换字典中特定字段:
print('Reading as dicts with type conversion')
field_types = [ ('Price', float),
('Change', float),
('Volume', int) ]
with open('stocks.csv') as f:
for row in csv.DictReader(f):
row.update((key, conversion(row[key]))
for key, conversion in field_types)
print(row)
错误处理与数据清洗
通常无需过多关注类型转换。实际应用中,CSV文件常存在缺失数据、损坏数据或其他导致转换失败的问题。除非数据确保证无误,否则必须考虑这些因素(建议增加适当的错误处理机制)。
使用Pandas进行高级分析
最后,若读取CSV数据旨在进行数据分析和统计,建议查看Pandas库。Pandas提供便捷的pandas.read_csv()函数,可将CSV数据加载到DataFrame对象中,进而生成各类统计、过滤数据及执行其他高级操作。
以上就是Python如何读写CSV数据的详细内容,更多关于Python读写CSV数据的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













