csv
--- CSV 文件讀寫?
源代碼: Lib/csv.py
CSV (Comma Separated Values) 格式是電子表格和數(shù)據(jù)庫中最常見的輸入、輸出文件格式。在 RFC 4180 規(guī)范推出的很多年前,CSV 格式就已經(jīng)被開始使用了,由于當(dāng)時(shí)并沒有合理的標(biāo)準(zhǔn),不同應(yīng)用程序讀寫的數(shù)據(jù)會(huì)存在細(xì)微的差別。這種差別讓處理多個(gè)來源的 CSV 文件變得困難。但盡管分隔符會(huì)變化,此類文件的大致格式是相似的,所以編寫一個(gè)單獨(dú)的模塊以高效處理此類數(shù)據(jù),將程序員從讀寫數(shù)據(jù)的繁瑣細(xì)節(jié)中解放出來是有可能的。
csv
模塊實(shí)現(xiàn)了 CSV 格式表單數(shù)據(jù)的讀寫。其提供了諸如“以兼容 Excel 的方式輸出數(shù)據(jù)文件”或“讀取 Excel 程序輸出的數(shù)據(jù)文件”的功能,程序員無需知道 Excel 所采用 CSV 格式的細(xì)節(jié)。此模塊同樣可以用于定義其他應(yīng)用程序可用的 CSV 格式或定義特定需求的 CSV 格式。
csv
模塊中的 reader
類和 writer
類可用于讀寫序列化的數(shù)據(jù)。也可使用 DictReader
類和 DictWriter
類以字典的形式讀寫數(shù)據(jù)。
參見
- 該實(shí)現(xiàn)在“Python 增強(qiáng)提議” - PEP 305 (CSV 文件 API) 中被提出
《Python 增強(qiáng)提議》提出了對(duì) Python 的這一補(bǔ)充。
模塊內(nèi)容?
csv
模塊定義了以下函數(shù):
- csv.reader(csvfile, dialect='excel', **fmtparams)?
返回一個(gè) reader 對(duì)象,該對(duì)象將逐行遍歷 csvfile。csvfile 可以是任何對(duì)象,只要這個(gè)對(duì)象支持 iterator 協(xié)議并在每次調(diào)用
__next__()
方法時(shí)都返回字符串,文件對(duì)象 和列表對(duì)象均適用。如果 csvfile 是文件對(duì)象,則打開它時(shí)應(yīng)使用newline=''
。 1 可選參數(shù) dialect 是用于不同的 CSV 變種的特定參數(shù)組。它可以是Dialect
類的子類的實(shí)例,也可以是list_dialects()
函數(shù)返回的字符串之一。另一個(gè)可選關(guān)鍵字參數(shù) fmtparams 可以覆寫當(dāng)前變種格式中的單個(gè)格式設(shè)置。有關(guān)變種和格式設(shè)置參數(shù)的完整詳細(xì)信息,請(qǐng)參見 變種與格式參數(shù) 部分。csv 文件的每一行都讀取為一個(gè)由字符串組成的列表。除非指定了
QUOTE_NONNUMERIC
格式選項(xiàng)(在這種情況下,未加引號(hào)的字段會(huì)轉(zhuǎn)換為浮點(diǎn)數(shù)),否則不會(huì)執(zhí)行自動(dòng)數(shù)據(jù)類型轉(zhuǎn)換。一個(gè)簡(jiǎn)短的用法示例:
>>> 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)?
返回一個(gè) writer 對(duì)象,該對(duì)象負(fù)責(zé)將用戶的數(shù)據(jù)在給定的文件類對(duì)象上轉(zhuǎn)換為帶分隔符的字符串。 csvfile 可以是任何具有
write()
方法的對(duì)象。 如果 csvfile 是一個(gè)文件對(duì)象,則打開它時(shí)應(yīng)使用newline=''
1。 可以給出可選的 dialect 形參用來定義一組特定 CSV 變種專屬的形參。 它可以是Dialect
類的某個(gè)子類的實(shí)例或是list_dialects()
函數(shù)所返回的字符串之一。 還可以給出另一個(gè)可選的 fmtparams 關(guān)鍵字參數(shù)來覆蓋當(dāng)前變種中的單個(gè)格式化形參。 有關(guān)各個(gè)變種和格式化形參的完整細(xì)節(jié),請(qǐng)參閱 變種與格式參數(shù) 部分。 為了盡量簡(jiǎn)化與實(shí)現(xiàn) DB API 的模塊之間的接口,None
值會(huì)被當(dāng)作空字符串寫入。 雖然這個(gè)轉(zhuǎn)換是不可逆的,但它可以簡(jiǎn)化 SQL NULL 數(shù)據(jù)值到 CSV 文件的轉(zhuǎn)儲(chǔ)而無需預(yù)處理從cursor.fetch*
調(diào)用返回的數(shù)據(jù)。 在被寫入之前所有其他非字符串?dāng)?shù)據(jù)都會(huì)先用str()
來轉(zhuǎn)轉(zhuǎn)為字符串。一個(gè)簡(jiǎn)短的用法示例:
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]])?
將 dialect 與 name 關(guān)聯(lián)起來。 name 必須是字符串。 變種的指定可以通過傳入一個(gè)
Dialect
的子類,或通過 fmtparams 關(guān)鍵字參數(shù),或是兩者同時(shí)傳入,此時(shí)關(guān)鍵字參數(shù)會(huì)覆蓋 dialect 形參。 有關(guān)變種和格式化形參的完整細(xì)節(jié),請(qǐng)參閱 變種與格式參數(shù) 部分。
- csv.unregister_dialect(name)?
從變種注冊(cè)表中刪除 name 對(duì)應(yīng)的變種。如果 name 不是已注冊(cè)的變種名稱,則拋出
Error
異常。
- csv.get_dialect(name)?
返回 name 對(duì)應(yīng)的變種。如果 name 不是已注冊(cè)的變種名稱,則拋出
Error
異常。該函數(shù)返回的是不可變的Dialect
對(duì)象。
- csv.list_dialects()?
返回所有已注冊(cè)變種的名稱。
- csv.field_size_limit([new_limit])?
返回解析器當(dāng)前允許的最大字段大小。如果指定了 new_limit,則它將成為新的最大字段大小。
csv
模塊定義了以下類:
- class csv.DictReader(f, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)?
創(chuàng)建一個(gè)對(duì)象,該對(duì)象在操作上類似于常規(guī) reader,但是將每行中的信息映射到一個(gè)
dict
,該 dict 的鍵由 fieldnames 可選參數(shù)給出。fieldnames 參數(shù)是一個(gè) sequence。如果省略 fieldnames,則文件 f 第一行中的值將用作字段名。無論字段名是如何確定的,字典都將保留其原始順序。
如果某一行中的字段多于字段名,則剩余數(shù)據(jù)會(huì)被放入一個(gè)列表,并與 restkey 所指定的字段名 (默認(rèn)為
None
) 一起保存。 如果某個(gè)非空白行的字段少于字段名,則缺失的值會(huì)使用 restval 的值來填充 (默認(rèn)為None
)。所有其他可選或關(guān)鍵字參數(shù)都傳遞給底層的
reader
實(shí)例。在 3.6 版更改: 返回的行現(xiàn)在的類型是
OrderedDict
。在 3.8 版更改: 現(xiàn)在,返回的行是
dict
類型。一個(gè)簡(jiǎn)短的用法示例:
>>> 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)?
創(chuàng)建一個(gè)對(duì)象,該對(duì)象在操作上類似常規(guī) writer,但會(huì)將字典映射到輸出行。 fieldnames 參數(shù)是由鍵組成的
序列
,它指定字典中值的順序,這些值會(huì)按指定順序傳遞給writerow()
方法并寫入文件 f。 如果字典缺少 fieldnames 中的鍵,則可選參數(shù) restval 用于指定要寫入的值。 如果傳遞給writerow()
方法的字典的某些鍵在 fieldnames 中找不到,則可選參數(shù) extrasaction 用于指定要執(zhí)行的操作。 如果將其設(shè)置為默認(rèn)值'raise'
,則會(huì)引發(fā)ValueError
。 如果將其設(shè)置為'ignore'
,則字典中的其他鍵值將被忽略。 所有其他可選或關(guān)鍵字參數(shù)都傳遞給底層的writer
實(shí)例。注意,與
DictReader
類不同,DictWriter
類的 fieldnames 參數(shù)不是可選參數(shù)。一個(gè)簡(jiǎn)短的用法示例:
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
類是一個(gè)容器類,其屬性包含有如何處理雙引號(hào)、空白符、分隔符等的信息。 由于缺少嚴(yán)格的 CSV 規(guī)格描述,不同的應(yīng)用程序會(huì)產(chǎn)生略有差別的 CSV 數(shù)據(jù)。Dialect
實(shí)例定義了reader
和writer
實(shí)例將具有怎樣的行為。所有可用的
Dialect
名稱會(huì)由list_dialects()
返回,并且它們可由特定的reader
和writer
類通過它們的初始化函數(shù) (__init__
) 來注冊(cè),例如:import csv with open('students.csv', 'w', newline='') as csvfile: writer = csv.writer(csvfile, dialect='unix') ^^^^^^^^^^^^^^
- class csv.unix_dialect?
unix_dialect
類定義了在 UNIX 系統(tǒng)上生成的 CSV 文件的常規(guī)屬性,即使用'\n'
作為換行符,且所有字段都有引號(hào)包圍。它在變種注冊(cè)表中的名稱是'unix'
。3.2 新版功能.
- class csv.Sniffer?
Sniffer
類用于推斷 CSV 文件的格式。Sniffer
類提供了兩個(gè)方法:- sniff(sample, delimiters=None)?
分析給定的 sample 并返回一個(gè)
Dialect
子類,該子類中包含了分析出的格式參數(shù)。如果給出可選的 delimiters 參數(shù),則該參數(shù)會(huì)被解釋為字符串,該字符串包含了可能的有效定界符。
- has_header(sample)?
分析 sample 文本(假定為 CSV 格式),如果發(fā)現(xiàn)其首行為一組列標(biāo)題則返回
True
。 在檢查每一列時(shí),將考慮是否滿足兩個(gè)關(guān)鍵標(biāo)準(zhǔn)之一來估計(jì) sample 是否包含標(biāo)題:第二至第 n 行包含數(shù)字值
第二至第 n 行包含字符串值,其中至少有一個(gè)值的長(zhǎng)度與該列預(yù)期標(biāo)題的長(zhǎng)度不同。
會(huì)對(duì)第一行之后的二十行進(jìn)行采樣;如果有超過一半的列 + 行符合標(biāo)準(zhǔn),則返回
True
。
備注
此方法是一個(gè)粗略的啟發(fā)式方式,有可能產(chǎn)生錯(cuò)誤的真值和假值。
使用 Sniffer
的示例:
with 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_NONNUMERIC?
指示
writer
對(duì)象為所有非數(shù)字字段加上引號(hào)。指示 reader 將所有未用引號(hào)引出的字段轉(zhuǎn)換為 float 類型。
- csv.QUOTE_NONE?
指示
writer
對(duì)象不使用引號(hào)引出字段。當(dāng) 定界符 出現(xiàn)在輸出數(shù)據(jù)中時(shí),其前面應(yīng)該有 轉(zhuǎn)義符。如果未設(shè)置 轉(zhuǎn)義符,則遇到任何需要轉(zhuǎn)義的字符時(shí),writer 都會(huì)拋出Error
異常。指示
reader
不對(duì)引號(hào)字符進(jìn)行特殊處理。
csv
模塊定義了以下異常:
- exception csv.Error?
該異常可能由任何發(fā)生錯(cuò)誤的函數(shù)拋出。
變種與格式參數(shù)?
為了更容易指定輸入和輸出記錄的格式,特定的一組格式參數(shù)組合為一個(gè) dialect(變種)。一個(gè) dialect 是一個(gè) Dialect
類的子類,它具有一組特定的方法和一個(gè) validate()
方法。創(chuàng)建 reader
或 writer
對(duì)象時(shí),程序員可以將某個(gè)字符串或 Dialect
類的子類指定為 dialect 參數(shù)。要想補(bǔ)充或覆蓋 dialect 參數(shù),程序員還可以單獨(dú)指定某些格式參數(shù),這些參數(shù)的名稱與下面 Dialect
類定義的屬性相同。
Dialect 類支持以下屬性:
- Dialect.delimiter?
一個(gè)用于分隔字段的單字符,默認(rèn)為
','
。
- Dialect.doublequote?
控制出現(xiàn)在字段中的 引號(hào)字符 本身應(yīng)如何被引出。當(dāng)該屬性為
True
時(shí),雙寫引號(hào)字符。如果該屬性為False
,則在 引號(hào)字符 的前面放置 轉(zhuǎn)義符。默認(rèn)值為True
。在輸出時(shí),如果 doublequote 是
False
,且 轉(zhuǎn)義符 未指定,且在字段中發(fā)現(xiàn) 引號(hào)字符 時(shí),會(huì)拋出Error
異常。
- Dialect.escapechar?
一個(gè)用于 writer 的單字符,用來在 quoting 設(shè)置為
QUOTE_NONE
的情況下轉(zhuǎn)義 定界符,在 doublequote 設(shè)置為False
的情況下轉(zhuǎn)義 引號(hào)字符。在讀取時(shí),escapechar 去除了其后所跟字符的任何特殊含義。該屬性默認(rèn)為None
,表示禁用轉(zhuǎn)義。在 3.11 版更改: An empty escapechar is not allowed.
- Dialect.lineterminator?
放在
writer
產(chǎn)生的行的結(jié)尾,默認(rèn)為'\r\n'
。備注
reader
經(jīng)過硬編碼,會(huì)識(shí)別'\r'
或'\n'
作為行尾,并忽略 lineterminator。未來可能會(huì)更改這一行為。
- Dialect.quotechar?
一個(gè)單字符,用于包住含有特殊字符的字段,特殊字符如 定界符 或 引號(hào)字符 或換行符。默認(rèn)為
'"'
。在 3.11 版更改: An empty quotechar is not allowed.
- Dialect.quoting?
控制 writer 何時(shí)生成引號(hào),以及 reader 何時(shí)識(shí)別引號(hào)。該屬性可以等于任何
QUOTE_*
常量(參見 模塊內(nèi)容 段落),默認(rèn)為QUOTE_MINIMAL
。
Reader 對(duì)象?
Reader 對(duì)象(DictReader
實(shí)例和 reader()
函數(shù)返回的對(duì)象)具有以下公開方法:
- csvreader.__next__()?
返回 reader 的可迭代對(duì)象的下一行,它可以是一個(gè)列表(如果對(duì)象是由
reader()
返回)或字典(如果是一個(gè)DictReader
實(shí)例),根據(jù)當(dāng)前Dialect
來解析。 通常你應(yīng)當(dāng)以next(reader)
的形式來調(diào)用它。
Reader 對(duì)象具有以下公開屬性:
- csvreader.dialect?
變種描述,只讀,供解析器使用。
- csvreader.line_num?
源迭代器已經(jīng)讀取了的行數(shù)。它與返回的記錄數(shù)不同,因?yàn)橛涗浛赡芸缭蕉嘈小?/p>
DictReader 對(duì)象具有以下公開屬性:
- csvreader.fieldnames?
字段名稱。如果在創(chuàng)建對(duì)象時(shí)未傳入字段名稱,則首次訪問時(shí)或從文件中讀取第一條記錄時(shí)會(huì)初始化此屬性。
Writer 對(duì)象?
Writer
對(duì)象(DictWriter
實(shí)例和 writer()
函數(shù)返回的對(duì)象)具有下面的公開方法。對(duì)于 Writer
對(duì)象,行 必須是(一組可迭代的)字符串或數(shù)字。對(duì)于 DictWriter
對(duì)象,行 必須是一個(gè)字典,這個(gè)字典將字段名映射為字符串或數(shù)字(數(shù)字要先經(jīng)過 str()
轉(zhuǎn)換類型)。請(qǐng)注意,輸出的復(fù)數(shù)會(huì)有括號(hào)包圍。這樣其他程序讀取 CSV 文件時(shí)可能會(huì)有一些問題(假設(shè)它們完全支持復(fù)數(shù))。
- csvwriter.writerow(row)?
將 row 形參寫入到 writer 的文件對(duì)象,根據(jù)當(dāng)前
Dialect
進(jìn)行格式化。 返回對(duì)下層文件對(duì)象的 write 方法的調(diào)用的返回值。在 3.5 版更改: 開始支持任意類型的迭代器。
- csvwriter.writerows(rows)?
將 rows*(即能迭代出多個(gè)上述 *row 對(duì)象的迭代器)中的所有元素寫入 writer 的文件對(duì)象,并根據(jù)當(dāng)前設(shè)置的變種進(jìn)行格式化。
Writer 對(duì)象具有以下公開屬性:
- csvwriter.dialect?
變種描述,只讀,供 writer 使用。
DictWriter 對(duì)象具有以下公開方法:
- DictWriter.writeheader()?
在 writer 的文件對(duì)象中,寫入一行字段名稱(字段名稱在構(gòu)造函數(shù)中指定),并根據(jù)當(dāng)前設(shè)置的變種進(jìn)行格式化。本方法的返回值就是內(nèi)部使用的
csvwriter.writerow()
方法的返回值。3.2 新版功能.
在 3.8 版更改: 現(xiàn)在
writeheader()
也返回其內(nèi)部使用的csvwriter.writerow()
方法的返回值。
例子?
讀取 CSV 文件最簡(jiǎn)單的一個(gè)例子:
import csv
with open('some.csv', newline='') as f:
reader = csv.reader(f)
for row in reader:
print(row)
讀取其他格式的文件:
import csv
with open('passwd', newline='') as f:
reader = csv.reader(f, delimiter=':', quoting=csv.QUOTE_NONE)
for row in reader:
print(row)
相應(yīng)最簡(jiǎn)單的寫入示例是:
import csv
with open('some.csv', 'w', newline='') as f:
writer = csv.writer(f)
writer.writerows(someiterable)
Since open()
is used to open a CSV file for reading, the file
will by default be decoded into unicode using the system default
encoding (see locale.getencoding()
). To decode a file
using a different encoding, use the encoding
argument of open:
import csv
with open('some.csv', newline='', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
print(row)
這同樣適用于寫入非系統(tǒng)默認(rèn)編碼的內(nèi)容:打開輸出文件時(shí),指定 encoding 參數(shù)。
注冊(cè)一個(gè)新的變種:
import csv
csv.register_dialect('unixpwd', delimiter=':', quoting=csv.QUOTE_NONE)
with open('passwd', newline='') as f:
reader = csv.reader(f, 'unixpwd')
Reader 的更高級(jí)用法——捕獲并報(bào)告錯(cuò)誤:
import csv, sys
filename = 'some.csv'
with open(filename, newline='') as f:
reader = csv.reader(f)
try:
for row in reader:
print(row)
except csv.Error as e:
sys.exit('file {}, line {}: {}'.format(filename, reader.line_num, e))
盡管該模塊不直接支持解析字符串,但仍可如下輕松完成:
import csv
for row in csv.reader(['one,two,three']):
print(row)
備注