csv

csv模块可以用于处理从电子表格和数据库导出的数据到带有字段和记录格式的文本文件,通常称为逗号分隔值(csv)格式,因为逗号通常用于分隔记录中的字段。

Reading

csv.reader(csvfile, dialect='excel', **fmtparams):返回一个读取器对象,它将在给定的csvfile中迭代。csvfile可以是任何支持iterator协议的对象,并且每次调用__next__()方法时返回一个字符串 - file objects和列表对象都是合适的。如果csvfile是文件对象,则应使用newline=''打开它。可以给出一个可选的方言参数,用于定义特定于某个CSV方言的一组参数。它可以是Dialect类的子类的实例或list_dialects()函数返回的字符串之一。可以给出其他可选的fmtparams关键字参数以覆盖当前方言中的各个格式化参数。从csv文件读取的每一行作为字符串列表返回。除非指定了QUOTE_NONNUMERIC格式选项(在这种情况下未引用的字段转换为浮点型),否则不会执行自动数据类型转换。
举例
从csv文件中读取数据, 可以使用reader()函数来创建一个读取对象. 这个读取对象顺序处理文件的每一行, 可以把它当成迭代器使用, 例如:

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

reader()的第一个参数指示源文本行, 在这个例子中, 是一个文件, 但它可以是任何可转换的对象(StringIO对象, lists等). 指定其他可选的参数可用于控制输入的数据如何被解析.
下面是测试的csv数据:

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

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

# python csv_study.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', 'ç']

如果你知道特定的列具有特定的类型, 你就可以自行转换, 但csv不会自动转换. 它会自动处理嵌入在一行字符串中(这个行和输入源文件的”行”意思是不同的)的换行符.

# cat testdata_1.csv
"Title 1","Title 2","Title 3","Title 4"
1,"first line
second line",08/18/07

Linux输出:

# python csv_study.py testdata_1.csv
['Title 1', 'Title 2', 'Title 3', 'Title 4']
['1', 'first line\nsecond line', '08/18/07']

Writing

csv.writer(csvfile, dialect='excel', **fmtparams):返回一个writer对象,负责将用户的数据转换为给定类文件对象上的分隔字符串。csvfile可以是具有write()方法的任何对象。如果csvfile是文件对象,则应使用newline=' ' 打开。可以给出可选的方言参数,用于定义特定于特定CSV方言的一组参数。它可以是Dialect类的子类的实例或list_dialects()函数返回的字符串之一。可以给出其他可选的fmtparams关键字参数以覆盖当前方言中的各个格式化参数。为了尽可能容易地与实现DB API的模块接口,值None被写为空字符串。虽然这不是可逆转换,但它可以更轻松地将SQL NULL数据值转储到CSV文件,而无需预处理从cursor.fetch*调用返回的数据。所有其他非字符串数据在写入之前用str()进行字符串化。
csvwriter.writerow(row):将行参数写入写入程序的文件对象,根据当前方言格式化。
csvwriter.writerows(rows):将所有行参数(如上所述的行对象的列表)写入作者的文件对象,根据当前方言格式化。
csvwriter.dialect:作者使用的方言的只读描述。
DictWriter.writeheader():用字段名写入一行(在构造函数中指定)。

举例
当你想把数据导入到其他应用程序中, 对CSV文件的写入也是非常方便的. 使用writer()函数来创建一个写入对象, 对于每一行, 使用writerow()来输出一行.

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())

Linux 输出:

# python csv_study.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

还有4种不同的引用选项, 它们作为常量定义在csv模块中.
QUOTE_ALL:不管是什么类型, 任何内容都加上引号
QUOTE_MINIMAL:这是默认的, 使用指定的字符引用各个域(如果解析器被配置为相同的dialect和选项时, 可能会让解析器在解析时产生混淆)
QUOTE_NONNUMERIC:引用那些不是整数或浮点数的域. 当使用读取对象时, 如果输入的域是没有引号, 那么它们会被转换成浮点数.
QUOTE_NONE:对所有的输出内容都不加引用, 当使用读取对象时, 引用字符看作是包含在每个域的值里(但在正常情况下, 他们被当成定界符而被去掉)

举例
The default quoting behavior is different for the writer, so the second and third columns in the previous example are not quoted. To add quoting, set the quoting argument to one of the other quoting modes.

import sys
import csv
unicode_chars = 'å∫ç'
with open(sys.argv[1], 'wt') as f:
writer = csv.writer(f, quoting=csv.QUOTE_NONNUMERIC)
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())

In this case, QUOTE_NONNUMERIC adds quotes around all columns that contain values that are not numbers.
输出:

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

Dialects

对于逗号分隔值文件,没有定义良好的标准,因此解析器需要灵活。这种灵活性意味着有许多参数可以控制csv如何解析或写入数据。它们不是将这些参数分别传递给阅读器和写入器,而是将它们组合成一个 dialect object.
Dialect classes可以通过名称进行注册,因此csv模块的调用者不需要预先知道参数设置。可以用list_dialects()检索完整的注册方言列表。

import csv
print(csv.list_dialects())

输出:

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

标准库包括三种方言:excel、excel标签和unix。excel dialect用于处理Microsoft excel的默认导出格式的数据,还可以与LibreOffice一起工作。unix dialect使用双引号引用所有字段,并使用\n作为记录分隔符。

Creating a Dialect

举例
如果不使用逗号来限制字段,则输入文件使用管道(|),如下所使用

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

可以使用适当的分隔符来注册一种新的dialect。

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

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

输出:

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

Dialect Parameters

一种dialect 指定解析或写入数据文件时使用的所有标记。下面的表列出了可以指定的文件格式的各个方面,从分隔列的方式到用于转义令牌的字符。

Attribute Default Meaning
delimiter , 用于分隔字段的单字符字符串。它默认为','。
doublequote True 控制在字段中出现的quotechar实例本身应如何引用。当True时,字符加倍。当False时,escapechar用作quotechar的前缀。默认为True。
escapechar None 写入器将分隔符(如果引用)转义的一个字符串设置为QUOTE_NONE和quotechar如果doublequote是False。读取时,escapechar会删除以下字符中的任何特殊含义。它默认为None,它禁用转义。
lineterminator \r\n 用于终止由writer生成的行的字符串。它默认为'\r\n'。
quotechar " 用于引用包含特殊字符(例如分隔符或quotechar)或包含换行字符的字段的单字符字符串。它默认为'"'。
quoting QUOTE_MINIMAL 控制何时报价应由作者生成并由读者识别。它可以接受任何QUOTE_*常量(参见Module Contents一节),默认为QUOTE_MINIMAL。
skipinitialspace False 当True时,紧跟分隔符后的空格将被忽略。默认值为False。

举例

import sys
import csv 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(
('coll', 1, '10/01/2010',
'Special chars: " \' {} to parse'.format(dialect.delimiter))
)
print()

这个程序显示了在使用不同的方言进行格式化时相同的数据是如何出现的。Linux输出:

Dialect: "escaped"

    delimiter   = ','        skipinitialspace  = 0
doublequote = 0 quoting = QUOTE_NONE
quotechar = '"' lineterminator = '\r\n'
escapechar = '\\' coll,1,10/01/2010,Special chars: \" ' \, to parse Dialect: "excel" delimiter = ',' skipinitialspace = 0
doublequote = 1 quoting = QUOTE_MINIMAL
quotechar = '"' lineterminator = '\r\n'
escapechar = None coll,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 coll 1 10/01/2010 "Special chars: "" ' to parse" Dialect: "singlequote" delimiter = ',' skipinitialspace = 0
doublequote = 1 quoting = QUOTE_ALL
quotechar = "'" lineterminator = '\r\n'
escapechar = None 'coll','1','10/01/2010','Special chars: " '' , to parse' Dialect: "unix" delimiter = ',' skipinitialspace = 0
doublequote = 1 quoting = QUOTE_ALL
quotechar = '"' lineterminator = '\n'
escapechar = None "coll","1","10/01/2010","Special chars: "" ' , to parse"

Automatically Detecting Dialects

csv.register_dialect(name[, dialect[, **fmtparams]]):将方言与名称相关联。名称必须是字符串。方言可以通过传递Dialect的子类或fmtparams关键字参数或两者来指定,其中关键字参数覆盖方言的参数。
csv.unregister_dialect(name):从方言注册表中删除与名称关联的方言。如果名称不是注册的方言名称,则会引发Error。
csv.get_dialect(name):返回与名称关联的方言。如果名称不是注册的方言名称,则会引发Error。此函数返回不可变的Dialect。
csv.list_dialects():返回所有注册方言的名称。
csv.field_size_limit([new_limit]):返回解析器允许的当前最大字段大小。如果给出new_limit,则这将成为新限制。

配置一个用于解析输入文件的方言的最佳方法是预先知道正确的设置。对于方言参数未知的数据,Sniffer 类可以用来做一个有根据的猜测。sniff()方法接受输入数据的一个示例,以及一个可选参数,提供可能的分隔符字符。
举例

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(
('coll', 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”的方言所演示的那样。Linux输出:

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

Using Field Names

class csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds):创建一个对象,其操作类似于普通读取器,但将读取的信息映射到一个dict中,其中的键由可选的fieldnames参数给出。fieldnames参数是一个sequence,其元素按顺序与输入数据的字段相关联。这些元素成为结果字典的键。如果省略fieldnames参数,则csvfile的第一行中的值将用作字段名称。如果读取的行具有比字段名序列更多的字段,则剩余数据将作为键值为restkey的序列添加。如果读取的行具有比字段名序列少的字段,则剩余的键使用可选的restval参数的值。任何其他可选或关键字参数都传递给底层的reader实例。
class csv.DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)
创建一个操作类似于常规writer的对象,但将字典映射到输出行。fieldnames参数是一个sequence,用于标识传递给writerow()方法的字典中的值被写入csvfile。如果字典在fieldnames中缺少键,则可选的restval参数指定要写入的值。如果传递给writerow()方法的字典包含fieldnames中未找到的键,则可选的extrasaction参数指示要执行的操作。如果设置为'raise',则会引发ValueError。如果设置为'ignore',则会忽略字典中的额外值。任何其他可选或关键字参数都传递给底层的writer实例。请注意,与DictReader类不同,DictWriter的fieldnames参数不是可选的。由于Python的dict对象没有排序,因此没有足够的信息来推断将该行写入到csvfile的顺序。

举例
另外, 在处理数据序列时, csv模块包含了一些将行作为字典进行处理的类. 类DictReader和类DictWriter将每一行转成字典对象, 可以传递字典键值, 或者从输入文件的第一行中推断出键值.

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

基于字典的读取和写入对象可以当作是基于序列对象的进一步实现, 它们使用相同的参数和API. 唯一的差别就是前者把每一行当成是字典而不是列表或元组.Linux输出:

# python csv_study.py testdata.csv
{'Title 2': 'first line\nsecond line', 'Title 1': '1', 'Title 3': '08/18/07', 'Title 4': None}
{'Title 2': 'a', 'Title 1': '1', 'Title 3': '08/18/07', 'Title 4': 'å'}
{'Title 2': 'b', 'Title 1': '2', 'Title 3': '08/19/07', 'Title 4': '∫'}
{'Title 2': 'c', 'Title 1': '3', 'Title 3': '08/20/07', 'Title 4': 'ç'}

DictWriter必须指定一个域名字的列表, 因为这样它才在输出时知道每个列的顺序.

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())

输出:

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

Python csv.md的更多相关文章

  1. Python CSV模块简介

    Table of Contents 1. CSV 1.1. 简介 1.2. 字典方式地读写 1.3. 其它 2. 参考资料 CSV csv文件格式是一种通用的电子表格和数据库导入导出格式.最近我调用R ...

  2. python csv 模块的使用

    python csv 模块的使用 歌曲推荐:攀登(live) csv 是用逗号分隔符来分隔列与列之间的. 1. csv的写入 1.简单的写入,一次写入一行 import csv with open(& ...

  3. Python CSV模块处理文件读写

    下面是一个简单的csv文件 Title,Release Date,Director And Now For Something Completely Different,1971,Ian MacNau ...

  4. Python CSV文件处理/读写及With as 用法

    可以不使用CSV模块 逐行处理: for line in open("samples/sample.csv"): title, year, director = line.spli ...

  5. Python CSV 超简明用法

    平常经常会用CSV存储数据,不可避免的会跟CSV文件的读写操作扯上关系. Python有CSV这个Package来解决这个问题,官网也有比较详细的教程 https://docs.python.org/ ...

  6. python csv模块的reader是一个迭代器,无法多次迭代

    在一个项目中,我需要多次遍历一个文本,该文本我是用csv.reader读取的.但后来发现,本文只对第一次循环有用,而之后的循环均为空白.经过排错后,我确定问题就出现在csv.reader()这一步.之 ...

  7. Selenium + Python +CSV

    绪论 首先写这个文章的时候仅仅花了2个晚上(我是菜鸟所以很慢),自己之前略懂selenium,但是不是很懂csv,这次相当于练手了. 第一章 环境介绍 具体实验环境 系统 Windows10教育版 1 ...

  8. python.csv 按行按列读取

    参考:https://blog.csdn.net/ly_ysys629/article/details/55107237 # header=0,表示文件第0行为列索引 # index_col=0,表示 ...

  9. Python os.md

    os 便携式访问操作系统的特定功能.os模块提供了对特定平台模块(如posix, nt, mac)的封装, 函数提供的api在很多平台上都可以相同使用, 所以使用os模块会变得很方便. 但不是所有函数 ...

随机推荐

  1. 用ASP.NET实现下载远程图片保存到本地的方法 保存抓取远程图片的方法

    以下介绍两种方法:1.利用WebRequest,WebResponse 类WebRequest wreq=WebRequest.Create("http://files.jb51.net/f ...

  2. C#根据byte前两位获取图片扩展名

    C#根据byte前两位获取图片扩展名 /// <summary> /// 根据byte前两位获取图片扩展名 /// </summary> /// <param name= ...

  3. VS2017 IIS 部署.net core web项目

    1.点击IIS,查看模块 查看是否安装了 AspNetCoreModule 模块,如果没有安装可下载:https://dotnet.microsoft.com/download 下载安装后,即可部署项 ...

  4. JdbcTemplate完全学习

    概述 Spring JDBC抽象框架core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的,JDBC模板类是第一种工作模式. JdbcTe ...

  5. NGINX: 统计网站的PV、UV、独立IP

    做网站的都知道,平常经常要查询下网站PV.UV等网站的访问数据,当然如果网站做了CDN的话,nginx本地的日志就没什么意义了,下面就对nginx网站的日志访问数据做下统计: 概念: UV(Uniqu ...

  6. Java - HashMap 多线程安全解析

    HashMap多线程并发问题分析 多线程put后可能导致get死循环 从前我们的Java代码因为一些原因使用了HashMap这个东西,但是当时的程序是单线程的,一切都没有问题.后来,我们的程序性能有问 ...

  7. VM虚拟机克隆_修改网络

    1.如果网络中没有VMware的网卡,记得重置即可 2.如果右上角没有了网络图标,直接 server NetworkManager restart 3.网络配置 1)在/etc/sysconfig/n ...

  8. Context 上下文

    全称:context 解释:上下文,在我们的开发的程序中,通常使用context上下文. 理解:结合实际生活我们可以把它理解为是语境,比如A说:我喜欢他. 那么这个他是谁,我们不知道,如果在这句话之前 ...

  9. 【代码笔记】iOS-键盘自适应弹出

    一,效果图. 二,工程图. 三,代码. ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIVie ...

  10. Boto Config File

    Boto是AWS SDK for Python,可以通过pip安装,也可以下载源码直接安装.直接安装挺方便的. 安装后参照AWS给出的Sample Project,连接S3,遍历一下buckets,获 ...