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