python standard library csv

python 标准库学习之csv

前言

2019年立的flag,今年继续,标准库系列文章继续更新。

今天是真冷啊,屋里头才16℃,只能用一张图来表示我的心情。

标准库 csv

文档路径

python标准库csv

CSV 文件格式

文件扩展名为.csv,通用的电子表格文件格式,经常使用在数据分析中。

分隔符可能有所差别, python中的csv模块提供了对csv文件的读写操作,非常方便。

csv 常用方法

csv.reader(csvfile,dialect='excel', ***fmtparams)

返回一个reader对象,该对象遍历csvfile。csv对象可以是任何对象,只要这个对象支持iteratable协议,并在每次调用__next__()方法时都返回字符串即可。如果csvfile是文件对象,则打开它时应使用newline=''。可选参数dialect是用于不同的csv文件类型,它可以是 Dialect 类的子类的实例,也可以是 list_dialects() 函数返回的字符串之一。完整的解释可以参考csv文件格式参数

csv文件的每一行都会默认当做字符串列表解析,除非指定了 QUOTE_NONNUMERIC 格式选项(在这种情况下,未加引号的字段会转换为浮点数),否则不会执行自动数据类型转换。

一个读文件例子

1
2
3
4
5
6
7
>>> import csv
>>> with open('eggs.csv', newline='') as csvfile:
... spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
... for row in spamreader:
... print(', '.join(row))
Spam, Spam, Spam, Spam, Spam, Baked Beans
Spam, Lovely Spam, Wonderful Spam

csv.writer(csvfile, dialect='excel', **fmtparams)

返回一个 writer 对象,该对象负责将用户的数据在给定的文件类对象上转换为带分隔符的字符串。csvfile 可以是具有 write() 方法的任何对象。如果 csvfile 是文件对象,则打开它时应使用 newline=''

为了尽量简化与数据库 API 模块之间的对接,None 值会写入为空字符串。虽然这个转换是不可逆的,但它让 SQL 空数据值转储到 CSV 文件更容易,而无需预处理从 cursor.fetch* 调用返回的数据。写入前,所有非字符串数据都先用 str() 转化为字符串再写入。

一个写文件例子

1
2
3
4
5
6
import csv
with open('eggs.csv', 'w', newline='') as csvfile:
spamwriter = csv.writer(csvfile, delimiter=' ',
quotechar='|', quoting=csv.QUOTE_MINIMAL)
spamwriter.writerow(['Spam'] * 5 + ['Baked Beans'])
spamwriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])

csv.register_dialect(name[, dialect[, **fmtparams]])

namedialect 关联起来。name 必须是字符串。要指定变种 (dialect),可以给出 Dialect 的子类,或给出 fmtparams 关键字参数,或两者都给出(此时关键字参数会覆盖 dialect 参数)。 有关方言和格式设置参数的完整详细信息,请参见 方言格式参数 部分。

其他方法:

  • csv.unregister_dialect(name)

    从变种注册表中删除 name 对应的变种。如果 name 不是已注册的变种名称,则抛出 Error 异常。

  • csv.get_dialect(name)

    返回 name 对应的变种。如果 name 不是已注册的变种名称,则抛出 Error 异常。该函数返回的是不可变的 Dialect 对象。

  • csv.list_dialects()

    返回所有已注册变种的名称。

  • csv.field_size_limit([new_limit])

    返回解析器当前允许的最大字段大小。如果指定了 new_limit,则它将成为新的最大字段大小。

csv模块定义的类

class csv.DictReader(*f*, *fieldnames=None*, *restkey=None*, *restval=None*, *dialect='excel'*, **args*, ***kwds*)

创建一个对象,该对象在操作上类似于常规 reader,但是将每行中的信息映射到一个 dict,该 dict 的键由 fieldnames 可选参数给出。

fieldnames 参数是一个 sequence。如果省略 fieldnames,则文件 f 第一行中的值将用作字段名。无论字段名是如何确定的,字典都将保留其原始顺序。

如果某一行中的字段多于字段名,则其余字段将放入列表中,字段名由 restkey 指定(默认为 None)。如果非空白行的字段少于字段名,则缺少的值将用 None 填充。

所有其他可选或关键字参数都传递给底层的 reader 实例。

3.8 中,返回的行是 dict 类型。

一个使用DictReader例子

1
2
3
4
5
6
7
8
9
10
11
>>> import csv
>>> with open('names.csv', newline='') as csvfile:
... reader = csv.DictReader(csvfile)
... for row in reader:
... print(row['first_name'], row['last_name'])
...
Eric Idle
John Cleese

>>> print(row)
{'first_name': 'John', 'last_name': 'Cleese'}

class csv.DictWriter(f, fieldnames, restval='', extrasaction='raise', dialect='excel', **args, **kwds)

创建一个对象,该对象在操作上类似常规 writer,但会将字典映射到输出行。 fieldnames 参数是由键组成的 序列,它指定字典中值的顺序,这些值会按指定顺序传递给 writerow() 方法并写入文件 f。 如果字典缺少 fieldnames 中的键,则可选参数 restval 用于指定要写入的值。 如果传递给 writerow() 方法的字典的某些键在 fieldnames 中找不到,则可选参数 extrasaction 用于指定要执行的操作。 如果将其设置为默认值 'raise',则会引发 ValueError。 如果将其设置为 'ignore',则字典中的其他键值将被忽略。 所有其他可选或关键字参数都传递给底层的 writer 实例。

注意,与 DictReader 类不同,DictWriter 类的 fieldnames 参数不是可选参数

一个使用DictWriter写入文件例子

1
2
3
4
5
6
7
8
9
10
import csv

with open('names.csv', 'w', newline='') as csvfile:
fieldnames = ['first_name', 'last_name']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

writer.writeheader()
writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})
writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'})
writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})

其他方法:

  • class csv.Dialect

    Dialect 类是主要依赖于其属性的容器类,用于将定义好的参数传递给特定的 readerwriter 实例。

  • class csv.excel

    excel 类定义了 Excel 生成的 CSV 文件的常规属性。它在变种注册表中的名称是 'excel'

  • class csv.excel_tab

    excel_tab 类定义了 Excel 生成的、制表符分隔的 CSV 文件的常规属性。它在变种注册表中的名称是 'excel-tab'

  • class csv.unix_dialect

    unix_dialect 类定义了在 UNIX 系统上生成的 CSV 文件的常规属性,即使用 '\n' 作为换行符,且所有字段都有引号包围。它在变种注册表中的名称是 'unix'

class csv.Sniffer

Sniffer 类用于推断 CSV 文件的格式。

Sniffer 类提供了两个方法:

  • sniff(sample, delimiters=None)

    分析给定的 sample 并返回一个 Dialect 子类,该子类中包含了分析出的格式参数。如果给出可选的 delimiters 参数,则该参数会被解释为字符串,该字符串包含了可能的有效定界符。

  • has_header(sample)

    分析示例文本(假定为 CSV 格式),如果第一行很可能是一系列列标题,则返回 True

一个使用Sniffer的例子:

1
2
3
4
5
ith open('example.csv', newline='') as csvfile:
dialect = csv.Sniffer().sniff(csvfile.read(1024))
csvfile.seek(0)
reader = csv.reader(csvfile, dialect)
# ... process CSV file contents here ...

csv 中定义的常量

  • csv.`QUOTE_ALL`

    指示 writer 对象给所有字段加上引号。

  • csv.`QUOTE_MINIMAL`

    指示 writer 对象仅为包含特殊字符(例如 定界符引号字符行结束符 中的任何字符)的字段加上引号。

  • csv.`QUOTE_NONNUMERIC`

    指示 writer 对象为所有非数字字段加上引号。指示 reader 将所有未用引号引出的字段转换为 float 类型。

  • csv.`QUOTE_NONE`

    指示 writer 对象不使用引号引出字段。当 定界符 出现在输出数据中时,其前面应该有 转义符。如果未设置 转义符,则遇到任何需要转义的字符时,writer 都会抛出 Error 异常。指示 reader 不对引号字符进行特殊处理。

csv模块定义了以下异常:

  • exception csv.`Error`

    该异常可能由任何发生错误的函数抛出。

备注

如果没有指定 newline='',则嵌入引号中的换行符将无法正确解析,并且在写入时,使用 \r\n 换行的平台会有多余的 \r 写入。由于 csv 模块会执行自己的(通用)换行符处理,因此指定 newline='' 应该总是安全的。

总结

csv模块是一个非常实用的处理csv文件的标准库,提供了两个核心类。一个是把csv文件对象当作字符串列表解析csv文件的类,另一个是把csv文件对象当作字典解析的类。

坚持原创技术分享,您的支持将鼓励我继续创作!