csv
— CSV 檔案讀取和寫入¶
原始碼: Lib/csv.py
所謂的 CSV(逗號分隔值)格式是電子表格和資料庫最常用的匯入和匯出格式。在 RFC 4180 中嘗試以標準化方式描述該格式之前,CSV 格式已經使用了多年。缺乏明確的標準意味著不同應用程式生成和使用的資料中經常存在細微的差異。這些差異使得處理來自多個來源的 CSV 檔案很麻煩。儘管分隔符和引號字元各不相同,但總體格式足夠相似,因此可以編寫一個可以高效操作此類資料的單個模組,從而向程式設計師隱藏讀取和寫入資料的細節。
csv
模組實現了以 CSV 格式讀取和寫入表格資料的類。它允許程式設計師說“以 Excel 首選的格式寫入此資料”或“從 Excel 生成的此檔案中讀取資料”,而無需知道 Excel 使用的 CSV 格式的精確細節。程式設計師還可以描述其他應用程式理解的 CSV 格式或定義他們自己的專用 CSV 格式。
csv
模組的 reader
和 writer
物件讀取和寫入序列。程式設計師還可以使用 DictReader
和 DictWriter
類以字典形式讀取和寫入資料。
另請參閱
- PEP 305 - CSV 檔案 API
提議將此新增到 Python 的 Python 增強提案。
模組內容¶
csv
模組定義了以下函式
- csv.reader(csvfile, dialect='excel', **fmtparams)¶
返回一個 reader 物件,該物件將處理給定 csvfile 中的行。 csvfile 必須是字串的可迭代物件,每個字串都採用 reader 定義的 csv 格式。 csvfile 通常是類檔案物件或列表。如果 csvfile 是檔案物件,則應使用
newline=''
開啟。[1] 可以提供可選的 dialect 引數,該引數用於定義特定於特定 CSV 方言的一組引數。它可以是Dialect
類的子類的例項,也可以是list_dialects()
函式返回的字串之一。可以提供其他可選的 fmtparams 關鍵字引數來覆蓋當前方言中的各個格式化引數。有關方言和格式化引數的完整詳細資訊,請參閱 方言和格式化引數 部分。從 csv 檔案讀取的每一行都作為字串列表返回。除非指定了
QUOTE_NONNUMERIC
格式選項(在這種情況下,未加引號的欄位將轉換為浮點數),否則不會執行自動資料型別轉換。一個簡短的用法示例
>>> 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=''
開啟[1]。可以提供可選的 dialect 引數,該引數用於定義特定於特定 CSV 方言的一組引數。它可以是Dialect
類的子類的例項,也可以是list_dialects()
函式返回的字串之一。可以提供其他可選的 fmtparams 關鍵字引數來覆蓋當前方言中的各個格式化引數。有關方言和格式化引數的完整詳細資訊,請參閱 方言和格式化引數 部分。為了儘可能方便地與實現 DB API 的模組進行互動,值None
被寫入為空字串。雖然這不是可逆的轉換,但這使得將 SQL NULL 資料值轉儲到 CSV 檔案中更容易,而無需預處理從cursor.fetch*
呼叫返回的資料。所有其他非字串資料在寫入之前都會使用str()
進行字串化。一個簡短的用法示例
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 關聯。 name 必須是字串。可以透過傳遞
Dialect
的子類、或透過 fmtparams 關鍵字引數,或兩者都指定方言,其中關鍵字引數會覆蓋方言的引數。有關方言和格式化引數的完整詳細資訊,請參閱 方言和格式化引數 部分。
- 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)¶
建立一個行為類似於常規讀取器的物件,但將每行中的資訊對映到一個
dict
,其鍵由可選的 fieldnames 引數給出。fieldnames 引數是一個 序列。如果省略 fieldnames,則檔案 f 的第一行的值將用作欄位名,並且將從結果中省略。如果提供了 fieldnames,則將使用它們,並且第一行將包含在結果中。無論如何確定欄位名,字典都會保留其原始順序。
如果某行的欄位數多於欄位名,則剩餘資料將放入列表中,並使用 restkey 指定的欄位名儲存(預設為
None
)。如果非空白行的欄位數少於欄位名,則缺失的值將用 restval 的值填充(預設為None
)。所有其他可選或關鍵字引數都將傳遞給底層的
reader
例項。如果傳遞給 fieldnames 的引數是一個迭代器,它將被強制轉換為一個
list
。在 3.6 版本中更改: 現在返回的行型別為
OrderedDict
。在 3.8 版本中更改: 現在返回的行型別為
dict
。一個簡短的用法示例
>>> 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)¶
建立一個行為類似於常規寫入器的物件,但將字典對映到輸出行。fieldnames 引數是一個
sequence
的鍵,用於標識傳遞給writerow()
方法的字典中值的寫入檔案 f 的順序。可選的 restval 引數指定如果字典在 fieldnames 中缺少鍵要寫入的值。如果傳遞給writerow()
方法的字典包含在 fieldnames 中找不到的鍵,則可選的 extrasaction 引數指示要採取的操作。如果設定為'raise'
(預設值),則會引發ValueError
異常。如果設定為'ignore'
,則會忽略字典中的額外值。任何其他可選或關鍵字引數都將傳遞給底層的writer
例項。請注意,與
DictReader
類不同,DictWriter
類的 fieldnames 引數不是可選的。如果傳遞給 fieldnames 的引數是一個迭代器,它將被強制轉換為一個
list
。一個簡短的用法示例
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
類是一個容器類,其屬性包含有關如何處理雙引號、空格、分隔符等的資訊。由於缺乏嚴格的 CSV 規範,不同的應用程式會產生略有不同的 CSV 資料。Dialect
例項定義了reader
和writer
例項的行為方式。所有可用的
Dialect
名稱都由list_dialects()
返回,並且可以透過其初始化器 (__init__
) 函式將其註冊到特定的reader
和writer
類,如下所示import csv with open('students.csv', 'w', newline='') as csvfile: writer = csv.writer(csvfile, dialect='unix')
- class csv.unix_dialect¶
unix_dialect
類定義了在 UNIX 系統上生成的 CSV 檔案的常用屬性,即使用'\n'
作為行終止符並引用所有欄位。它使用方言名稱'unix'
註冊。在 3.2 版本中新增。
- class csv.Sniffer¶
Sniffer
類用於推斷 CSV 檔案的格式。Sniffer
類提供了兩個方法- sniff(sample, delimiters=None)¶
分析給定的sample並返回一個反映所找到引數的
Dialect
子類。如果給定了可選的delimiters引數,則將其解釋為包含可能有效的分隔符字元的字串。
- has_header(sample)¶
分析樣本文字(假定為 CSV 格式)並返回
True
如果第一行看起來是一系列列標題。檢查每一列,將考慮以下兩個關鍵標準之一來估計樣本是否包含標題第二行到第 n 行包含數值
第二行到第 n 行包含字串,其中至少有一個值的長度與該列的推定標題的長度不同。
取樣第一行之後的二十行;如果超過一半的列 + 行滿足條件,則返回
True
。
注意
此方法是一種粗略的啟發式方法,可能會產生誤報和漏報。
關於 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
物件永不引用欄位。噹噹前 delimiter 出現在輸出資料中時,它前面會加上當前 escapechar 字元。如果未設定 escapechar,則如果遇到任何需要轉義的字元,寫入器將引發Error
。指示
reader
物件不對引號字元執行任何特殊處理。
- csv.QUOTE_NOTNULL¶
指示
writer
物件引用所有不是None
的欄位。這與QUOTE_ALL
類似,只是如果欄位值為None
,則會寫入一個空(未引用)的字串。指示
reader
物件將空(未引用)的欄位解釋為None
,否則其行為與QUOTE_ALL
相同。在 3.12 版本中新增。
- csv.QUOTE_STRINGS¶
指示
writer
物件始終在字串欄位周圍放置引號。這與QUOTE_NONNUMERIC
類似,只是如果欄位值為None
,則會寫入一個空(未引用)的字串。指示
reader
物件將空(未引用)的字串解釋為None
,否則其行為與QUOTE_NONNUMERIC
相同。在 3.12 版本中新增。
csv
模組定義了以下異常
- exception csv.Error¶
當檢測到錯誤時,任何函式都會引發此異常。
方言和格式化引數¶
為了更容易指定輸入和輸出記錄的格式,特定的格式化引數被分組到方言中。方言是 Dialect
類的子類,其中包含描述 CSV 檔案格式的各種屬性。建立 reader
或 writer
物件時,程式設計師可以指定一個字串或 Dialect
類的子類作為方言引數。除了或代替 dialect 引數,程式設計師還可以指定單個格式化引數,這些引數的名稱與下面為 Dialect
類定義的屬性相同。
方言支援以下屬性
- Dialect.delimiter¶
用於分隔欄位的單字元字串。它預設為
','
。
- Dialect.doublequote¶
控制如何引用出現在欄位內的 quotechar 例項。當
True
時,該字元會加倍。當False
時,escapechar 用作 quotechar 的字首。它預設為True
。在輸出時,如果 doublequote 為
False
並且未設定 escapechar,則如果在欄位中找到 quotechar,將引發Error
。
- Dialect.escapechar¶
一個單字元字串,當quoting設定為
QUOTE_NONE
,且當doublequote為False
時,由寫入器用於轉義delimiter或quotechar。 在讀取時,escapechar 會刪除後續字元的任何特殊含義。 它預設為None
,表示停用轉義。3.11 版本已更改: 不允許使用空的 escapechar。
- Dialect.lineterminator¶
用於終止
writer
生成的行的字串。 它預設為'\r\n'
。注意
reader
被硬編碼為識別'\r'
或'\n'
作為行尾,並忽略 lineterminator。 此行為在未來可能會更改。
- Dialect.quotechar¶
用於引用包含特殊字元(例如 delimiter 或 quotechar)或包含換行符的欄位的單字元字串。 它預設為
'"'
。3.11 版本已更改: 不允許使用空的 quotechar。
- Dialect.quoting¶
控制寫入器何時生成引號以及讀取器何時識別引號。 它可以採用任何 QUOTE_* 常量,並預設為
QUOTE_MINIMAL
。
讀取器物件¶
讀取器物件(DictReader
例項和 reader()
函式返回的物件)具有以下公共方法
- csvreader.__next__()¶
以列表形式(如果物件是從
reader()
返回的)或字典形式(如果它是DictReader
例項)返回讀取器的可迭代物件的下一行,並根據當前的Dialect
進行解析。 通常你應該將其作為next(reader)
呼叫。
讀取器物件具有以下公共屬性
- csvreader.dialect¶
一個對解析器使用的方言的只讀描述。
- csvreader.line_num¶
從源迭代器讀取的行數。 這與返回的記錄數不同,因為記錄可以跨越多行。
DictReader 物件具有以下公共屬性
- DictReader.fieldnames¶
如果未在建立物件時作為引數傳遞,則此屬性將在首次訪問或從檔案中讀取第一條記錄時初始化。
寫入器物件¶
writer
物件(DictWriter
例項和 writer()
函式返回的物件)具有以下公共方法。 對於 writer
物件,row 必須是字串或數字的可迭代物件,對於 DictWriter
物件,row 必須是將欄位名稱對映到字串或數字的字典(首先透過 str()
傳遞它們)。 請注意,複數會用括號括起來寫入。 這可能會給其他讀取 CSV 檔案的程式帶來一些問題(假設它們完全支援複數)。
- csvwriter.writerow(row)¶
根據當前的
Dialect
將 row 引數寫入寫入器的檔案物件。 返回對底層檔案物件的 write 方法的呼叫返回值。3.5 版本已更改: 添加了對任意可迭代物件的支援。
- csvwriter.writerows(rows)¶
根據當前方言將 rows 中的所有元素(一個如上所述的 row 物件的可迭代物件)寫入寫入器的檔案物件。
寫入器物件具有以下公共屬性
- csvwriter.dialect¶
一個對寫入器使用的方言的只讀描述。
DictWriter 物件具有以下公共方法
- DictWriter.writeheader()¶
將包含欄位名稱(如建構函式中指定)的行寫入寫入器的檔案物件,並根據當前的方言進行格式化。 返回內部使用的
csvwriter.writerow()
呼叫的返回值。在 3.2 版本中新增。
3.8 版本已更改:
writeheader()
現在還返回其內部使用的csvwriter.writerow()
方法的返回值。
示例¶
讀取 CSV 檔案的最簡單示例
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)
相應的最簡單的寫入示例是
import csv
with open('some.csv', 'w', newline='') as f:
writer = csv.writer(f)
writer.writerows(someiterable)
由於 open()
用於開啟 CSV 檔案進行讀取,該檔案預設會使用系統預設編碼(請參閱 locale.getencoding()
)解碼為 unicode。 要使用不同的編碼解碼檔案,請使用 open 的 encoding
引數
import csv
with open('some.csv', newline='', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
print(row)
這同樣適用於使用系統預設編碼以外的編碼寫入:在開啟輸出檔案時指定 encoding 引數。
註冊新的方言
import csv
csv.register_dialect('unixpwd', delimiter=':', quoting=csv.QUOTE_NONE)
with open('passwd', newline='') as f:
reader = csv.reader(f, 'unixpwd')
稍微高階一點的讀取器用法——捕獲和報告錯誤
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)
腳註