原文:https://pythoncaff.com/docs/pymotw/csv-comma-separated-value-files/125

csv 模块主要用于处理从电子数据表格或数据库中导入到文本文件的数据,通常简称为comma-separated value (CSV)格式因为逗号用于分离每条记录的各个字段。

读取##

从 CSV 文件中读取数据, 可以使用 reader() 函数来创建一个读取对象。 这个读取对象顺序处理文件的每一行,可以把它当成迭代器使用, 例如:

csv_reader.py

import csv
import sys with open(sys.argv[1], 'rt') as f:
reader = csv.reader(f)
for row in reader:
print(row)

reader() 的第一个参数指源文本,在这个例子中,是一个文件,但它可以是任何可迭代对象( StringIO 实例,list 等)。第二个参数是可选的,可用于控制输入的数据如何被解析。

"Title 1","Title 2","Title 3","Title 4"
1,"a",08/18/07,"å"
2,"b",08/19/07,"∫"
3,"c",08/20/07,"ç"

它被读取时,输入数据的每一行被转换为一个字符串列表。

$ python3 csv_reader.py testdata.csv

['Title 1', 'Title 2', 'Title 3', 'Title 4']
['1', 'a', '08/18/07', 'å']
['2', 'b', '08/19/07', '∫']
['3', 'c', '08/20/07', 'ç']

解析器会自动处理嵌入在一行字符串中的换行符,这也是输出中的一行数据可能和输入的一行不同的原因。

"Title 1","Title 2","Title 3"
1,"first line
second line",08/18/07

输入中带有换行符的字段在解析器返回时保留内部换行符。

$ python3 csv_reader.py testlinebreak.csv

['Title 1', 'Title 2', 'Title 3']
['1', 'first line\nsecond line', '08/18/07']

非法操作 翻译于 5个月前
 
由 Summer 审阅
 

写入##

写入 CSV 文件和读取它们一样简单。使用 writer() 方法创建一个写入对象,然后使用 writerow() 去输出每一行。

csv_writer.py

import csv
import sys unicode_chars = 'å∫ç' with open(sys.argv[1], 'wt') as f:
writer = csv.writer(f)
writer.writerow(('Title 1', 'Title 2', 'Title 3', 'Title 4'))
for i in range(3):
row = (
i + 1,
chr(ord('a') + i),
'08/{:02d}/07'.format(i + 1),
unicode_chars[i],
)
writer.writerow(row) print(open(sys.argv[1], 'rt').read())

这个例子的输出和上面读取的例子看起来有些不同,是因为这里有的值没有加引号。

$ python3 csv_writer.py testout.csv

Title 1,Title 2,Title 3,Title 4
1,a,08/01/07,å
2,b,08/02/07,∫
3,c,08/03/07,ç

引用##

写入时,默认的引用行为不同,所以之前示例中的第二和第三个字段未被引用。 要添加引号,请将 quoting 参数设置为其他引用模式。

writer = csv.writer(f, quoting=csv.QUOTE_NONNUMERIC)

在这个例子中, QUOTE_NONNUMERIC 会给所有字段值不是数字的值添加引号。

$ python3 csv_writer_quoted.py testout_quoted.csv

"Title 1","Title 2","Title 3","Title 4"
1,"a","08/01/07","å"
2,"b","08/02/07","∫"
3,"c","08/03/07","ç"

有四种不同的引用选项,在 csv 模块中被定义为常量。

QUOTE_ALL

无论什么类型的字段都会被引用。

QUOTE_MINIMAL

这是默认的选项, 使用指定的字符引用各字段(如果解析器被配置为相同的dialect和选项时,可能会让解析器在解析时产生混淆)。

QUOTE_NONNUMERIC

引用那些不是整数或浮点数的字段。当使用读取对象时, 如果输入的字段是没有引号的, 那么它们会被转换成浮点数。

QUOTE_NONE

对所有的输出内容都不加引用,当使用读取对象时,引用字符看作是包含在每个字段的值里(但在正常情况下,它们被当成定界符而被去掉)。

非法操作 翻译于 4个月前
 
由 Summer 审阅
 

编码风格##

其实没有一个标准定义这类逗号分隔值的文件,所以解析器需要很灵活,通过很多参数去控制如何解析 csv 或给其写入数据。但这并不是每个参数在写入或读取 csv 时分别传入,而是统一分组为一个 编码风格 对象。

Dialect 类可以通过名字注册,因此 csv 模块调用它时不必预先知道相关的参数设置。所有注册过的编码风格列表可以通过 list_dialects() 方法查看。

csv_list_dialects.py

import csv

print(csv.list_dialects())

标准库提供了三种编码风格,分别为: excel,  excel-tabs 和 unix。 excel 编码风格用来处理默认来自 Microsoft Excel 格式的数据的,同样可用于处理来自 LibreOffice 格式的。 unix 编码风格将所有字段通过双引号引用,并用 \n 做为每条记录的分隔符。

$ python3 csv_list_dialects.py

['excel', 'excel-tab', 'unix']

创建一个编码风格##

如果不使用逗号分隔字段,输入文件使用竖杠( | ),就像这样

"Title 1"|"Title 2"|"Title 3"
1|"first line
second line"|08/18/07

一个新的编码风格可以使用不同的分隔符进行注册。

csv_dialect.py

import csv

csv.register_dialect('pipes', delimiter='|')

with open('testdata.pipes', 'r') as f:
reader = csv.reader(f, dialect='pipes')
for row in reader:
print(row)

使用「竖杠」的编码风格,可以像使用逗号一样读取文件。

$ python3 csv_dialect.py

['Title 1', 'Title 2', 'Title 3']
['1', 'first line\nsecond line', '08/18/07']

非法操作 翻译于 4个月前
 
由 Summer 审阅
 

编码风格参数##

编码风格指定解析或写入数据文件时使用的所有标记。下表列出了可以设定的属性,从字段的分隔方式到用于转义标记的字符。

CSV 编码风格参数

属性 默认 含义
delimiter , 字段分隔符(单字符)
doublequote True 控制 quotechar 实例是否翻倍
escapechar None 用于表示转义序列的字符
lineterminator \r\n 写入时用来换行的字符
quotechar " 引用含特殊值字段的字符(一个字符)
quoting QUOTE_MINIMAL 控制前面表述的引用行为
skipinitialspace False 是否在字段分隔符后忽略空格

csv_dialect_variations.py

import csv
import sys csv.register_dialect('escaped',
escapechar='\\',
doublequote=False,
quoting=csv.QUOTE_NONE,
)
csv.register_dialect('singlequote',
quotechar="'",
quoting=csv.QUOTE_ALL,
) quoting_modes = {
getattr(csv, n): n
for n in dir(csv)
if n.startswith('QUOTE_')
} TEMPLATE = '''\
Dialect: "{name}" delimiter = {dl!r:<6} skipinitialspace = {si!r}
doublequote = {dq!r:<6} quoting = {qu}
quotechar = {qc!r:<6} lineterminator = {lt!r}
escapechar = {ec!r:<6}
''' for name in sorted(csv.list_dialects()):
dialect = csv.get_dialect(name) print(TEMPLATE.format(
name=name,
dl=dialect.delimiter,
si=dialect.skipinitialspace,
dq=dialect.doublequote,
qu=quoting_modes[dialect.quoting],
qc=dialect.quotechar,
lt=dialect.lineterminator,
ec=dialect.escapechar,
)) writer = csv.writer(sys.stdout, dialect=dialect)
writer.writerow(
('col1', 1, '10/01/2010',
'Special chars: " \' {} to parse'.format(
dialect.delimiter))
)
print()

这段程序演示了当使用几种不同的编码风格格式化时,相同的数据如何展示。

$ python3 csv_dialect_variations.py

Dialect: "escaped"

  delimiter   = ','       skipinitialspace = 0
doublequote = 0 quoting = QUOTE_NONE
quotechar = '"' lineterminator = '\r\n'
escapechar = '\\' col1,1,10/01/2010,Special chars: \" ' \, to parse Dialect: "excel" delimiter = ',' skipinitialspace = 0
doublequote = 1 quoting = QUOTE_MINIMAL
quotechar = '"' lineterminator = '\r\n'
escapechar = None col1,1,10/01/2010,"Special chars: "" ' , to parse" Dialect: "excel-tab" delimiter = '\t' skipinitialspace = 0
doublequote = 1 quoting = QUOTE_MINIMAL
quotechar = '"' lineterminator = '\r\n'
escapechar = None col1 1 10/01/2010 "Special chars: "" ' to parse" Dialect: "singlequote" delimiter = ',' skipinitialspace = 0
doublequote = 1 quoting = QUOTE_ALL
quotechar = "'" lineterminator = '\r\n'
escapechar = None 'col1','1','10/01/2010','Special chars: " '' , to parse' Dialect: "unix" delimiter = ',' skipinitialspace = 0
doublequote = 1 quoting = QUOTE_ALL
quotechar = '"' lineterminator = '\n'
escapechar = None "col1","1","10/01/2010","Special chars: "" ' , to parse"

自动检测编码风格##

配置一个输入文件的编码风格的最好的办法是提前知道哪种编码风格是正确的。对于那些编码风格未知的参数, Sniffer 类可用于做有效的猜测。 sniff() 方法会获取输入数据的一个样本和一个可选参数,给出可能的分隔符。

csv_dialect_sniffer.py

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) # 为所有已知的编码风格生成样本数据
samples = []
for name in sorted(csv.list_dialects()):
buffer = StringIO()
dialect = csv.get_dialect(name)
writer = csv.writer(buffer, dialect=dialect)
writer.writerow(
('col1', 1, '10/01/2010',
'Special chars " \' {} to parse'.format(
dialect.delimiter))
)
samples.append((name, dialect, buffer.getvalue())) # 猜测样本的编码风格,然后用猜测结果来解析数据。
sniffer = csv.Sniffer()
for name, expected, sample in samples:
print('Dialect: "{}"'.format(name))
print('In: {}'.format(sample.rstrip()))
dialect = sniffer.sniff(sample, delimiters=',\t')
reader = csv.reader(StringIO(sample), dialect=dialect)
print('Parsed:\n {}\n'.format(
'\n '.join(repr(r) for r in next(reader))))

sniff() 方法返回一个包含了解析数据的参数的 Dialect 实例。结果并不一定是正确的,例如这个例子中的「escaped」。

$ python3 csv_dialect_sniffer.py

Dialect: "escaped"
In: col1,1,10/01/2010,Special chars \" ' \, to parse
Parsed:
'col1'
'1'
'10/01/2010'
'Special chars \\" \' \\'
' to parse' Dialect: "excel"
In: col1,1,10/01/2010,"Special chars "" ' , to parse"
Parsed:
'col1'
'1'
'10/01/2010'
'Special chars " \' , to parse' Dialect: "excel-tab"
In: col1 1 10/01/2010 "Special chars "" ' to parse"
Parsed:
'col1'
'1'
'10/01/2010'
'Special chars " \' \t to parse' Dialect: "singlequote"
In: 'col1','1','10/01/2010','Special chars " '' , to parse'
Parsed:
'col1'
'1'
'10/01/2010'
'Special chars " \' , to parse' Dialect: "unix"
In: "col1","1","10/01/2010","Special chars "" ' , to parse"
Parsed:
'col1'
'1'
'10/01/2010'
'Special chars " \' , to parse'

非法操作 翻译于 4个月前
 
由 Summer 审阅
 

使用字段名称##

除了处理数据序列之外,csv 模块还提供了用于处理将字典作为行的类,以便可以对字段进行命名。 DictReader  和  DictWriter  将行翻译成字典而不是序列。字典的键可以被传入或者从输入的第一行(当该行包含标题时)推断出来。

csv_dictreader.py

import csv
import sys with open(sys.argv[1], 'rt') as f:
reader = csv.DictReader(f)
for row in reader:
print(row)

基于字典的读取器和写入器被实现为基于序列的类的包装器,并使用相同的方法和参数。读取器唯一的区别是行作为 OrderedDict 实例返回而不是列表或者元组(早期的 Python 版本中,行作为常规 dict 实例返回)。

$ python3 csv_dictreader.py testdata.csv

OrderedDict([('Title 1', '1'), ('Title 2', 'a'), ('Title 3',
'08/18/07'), ('Title 4', 'å')])
OrderedDict([('Title 1', '2'), ('Title 2', 'b'), ('Title 3',
'08/19/07'), ('Title 4', '∫')])
OrderedDict([('Title 1', '3'), ('Title 2', 'c'), ('Title 3',
'08/20/07'), ('Title 4', 'ç')])

必须要给 DictWriter 一个字段名称列表,以至于让它在输出的时候如何排序。

csv_dictwriter.py

import csv
import sys fieldnames = ('Title 1', 'Title 2', 'Title 3', 'Title 4')
headers = {
n: n
for n in fieldnames
}
unicode_chars = 'å∫ç' with open(sys.argv[1], 'wt') as f: writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader() for i in range(3):
writer.writerow({
'Title 1': i + 1,
'Title 2': chr(ord('a') + i),
'Title 3': '08/{:02d}/07'.format(i + 1),
'Title 4': unicode_chars[i],
}) print(open(sys.argv[1], 'rt').read())

字段名称不会被自动写入到文件,但是他们可以显示地使用 writeheader() 方法写入。

$ python3 csv_dictwriter.py testout.csv

Title 1,Title 2,Title 3,Title 4
1,a,08/01/07,å
2,b,08/02/07,∫
3,c,08/03/07,ç

(转)csv — 逗号分隔值文件格式的更多相关文章

  1. CSV (逗号分隔值文件格式)

    逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本).纯文本意味着该文件是一个字符序列,不 ...

  2. C#对.CSV格式的文件--逗号分隔值文件 的读写操作及上传ftp服务器操作方法总结

    前言 公司最近开发需要将数据保存到.csv文件(逗号分隔值 文件)中然后上传到ftp服务器上,供我们系统还有客户系统调用,之前完全没有接触过这个,所以先来看看百度的解释:逗号分隔值(Comma-Sep ...

  3. 字符串 CSV解析 表格 逗号分隔值 通讯录 电话簿 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  4. LINQ to XML 从逗号分隔值 (CSV) 文件生成 XML 文件

    参考:http://msdn.microsoft.com/zh-cn/library/bb387090.aspx 本示例演示如何使用 语言集成查询 (LINQ) 和 LINQ to XML 从逗号分隔 ...

  5. python开发_csv(Comma Separated Values)_逗号分隔值_常用导入导出格式_完整版_博主推荐

    ## 最近出了一趟差,是从20号去的,今天回来...# 就把最近学习的python内容给大家分享一下...#''' 在python中,CSV(Comma Separated Values),从字面上面 ...

  6. jmeter问题处理随笔1 - CSV取值数据异常处理(包含"号,","号的情况)

    背景 jmeter测试中通过CSV进行用例数据的管理,在result断言中间需要使用json格式的数据,会包含 " ",",这个时候发现CSV取值会报错或者乱码 解决 用 ...

  7. CSV是什么文件格式【转】

    本文转载自:https://blog.csdn.net/huyanping/article/details/6384687 CSV即Comma Separate Values,这种文件格式经常用来作为 ...

  8. SQL建模错误--逗号分隔值

    最近帮一个客户分析SQL语句的问题,大致经过如下 场景: 委托方有一个用于追踪他们产品的系统,每个产品都会卖给许多客户:但是客户又被从业务上分成两类,一类是带有合作伙伴性质的,这个 合作伙伴通常会给予 ...

  9. python 逗号分隔值文件的操作

随机推荐

  1. myBatis中if test 字符串注意事项

    错误写法: <if test="userName == 'boshen'"> AND `USER_NAME` = #{userName} </if> 正确写 ...

  2. MySQL处理表字段小技巧

    MySQL利用正则函数替换值 update dateTest set date=REPLACE(date,'/','') where date REGEXP '\/'; SQL语句讲解: -- 将 所 ...

  3. application.properties /application.yml官网查看配置;springboot application.properties 官网查看,info yml 查看;springboot.yml查看info;springboot.yml查看Actuator监控中心info

    官网查看: https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#appendix 查看info ...

  4. 第26章:MongoDB-索引

    ①索引 索引本质上是树,最小的值在最左边的叶子上,最大的值在最右边的叶子上,使用索引可以提高查询速度(而不用全表扫描),也可以预防脏数据的插入(如唯一索引). 索引通常能够极大的提高查询的效率,如果没 ...

  5. UVaLive 3704 Cellular Automaton (循环矩阵 + 矩阵快速幂)

    题意:一个细胞自动机包含 n 个格子,每个格子取值是 0 ~ m-1,给定距离,则每次操作后每个格子的值将变成到它距离不超过 d 的所有格子在操作之前的值之和取模 m 后的值,其中 i 和 j 的距离 ...

  6. 2.2.10数据类型String的常量池特性

    在JVM中具有String常量池缓存的功能 package com.cky.test; /** * Created by edison on 2017/12/8. */ public class Te ...

  7. 20155326刘美岑 2016-2017-2 《Java程序设计》第5周学习总结

    20155326刘美岑 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 使用 try.catch (1)java中所有的错误都会被打包为对象,如果愿意,可以尝 ...

  8. 23种设计模式(1)-Facade设计模式

    前记 曾经我遇见的一个需求是这样的,接口A有个方法void methodA(),类B需要实现接口A的methodA()方法,并且在类B中需要把methodA()方法内部处理逻辑获得的结果利用C类实例的 ...

  9. PAT甲级 1128. N Queens Puzzle (20)

    1128. N Queens Puzzle (20) 时间限制 300 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue The & ...

  10. 无法链接glew的解决办法-编译开源库出现: error LNK2001: 无法解析的外部符号

    无法链接glew的解决办法-编译开源库出现: error LNK2001: 无法解析的外部符号 参考官方配置指南:http://glew.sourceforge.net/install.html 1. ...