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='excel', **fmtparams)¶
將 dialect 與 name 關聯。name 必須是字串。方言可以透過傳遞
Dialect
的子類,或透過 fmtparams 關鍵字引數,或兩者兼有來指定,其中關鍵字引數會覆蓋方言的引數。有關方言和格式化引數的完整詳細資訊,請參見 方言和格式化引數 部分。
- csv.list_dialects()¶
返回所有已註冊方言的名稱。
- csv.field_size_limit()¶
- 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
,其鍵由可選的 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)¶
建立一個類似於常規 writer 的物件,但將字典對映到輸出行。fieldnames 引數是一個鍵的
序列
,用於標識傳遞給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_MINIMAL¶
指示
writer
物件僅引用那些包含特殊字元(如 delimiter、quotechar、'\r'
、'\n'
或 lineterminator 中的任何字元)的欄位。
- csv.QUOTE_NONNUMERIC¶
指示
writer
物件引用所有非數字欄位。指示
reader
物件將所有未加引號的欄位轉換為float
型別。備註
某些數值型別,如
bool
、Fraction
或IntEnum
,其字串表示無法轉換為float
。它們無法在QUOTE_NONNUMERIC
和QUOTE_STRINGS
模式下讀取。
- csv.QUOTE_NONE¶
指示
writer
物件從不引用欄位。噹噹前的 delimiter、quotechar、escapechar、'\r'
、'\n'
或 lineterminator 中的任何字元出現在輸出資料中時,它前面會加上當前的 escapechar 字元。如果未設定 escapechar,則在遇到任何需要轉義的字元時,writer 將引發Error
。將 quotechar 設定為None
> 以防止其轉義。指示
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¶
writer 用於轉義需要轉義的字元的單字元字串
如果 quoting 設定為
QUOTE_NONE
,則 delimiter、quotechar、'\r'
、'\n'
和 lineterminator 中的任何字元都會被轉義;如果 doublequote 為
False
,則 quotechar 會被轉義;escapechar 本身。
讀取時,escapechar 會移除其後字元的任何特殊含義。它預設為
None
,表示停用轉義。在 3.11 版本發生變更: 不允許空的 escapechar。
- Dialect.lineterminator¶
用於終止
writer
生成的行的字串。預設為'\r\n'
。備註
reader
硬編碼為識別'\r'
> 或'\n'
作為行尾,並忽略 lineterminator。此行為將來可能會改變。
- Dialect.quotechar¶
用於引用包含特殊字元(如 delimiter 或 quotechar)或包含換行符(
'\r'
、'\n'
或 lineterminator 中的任何字元)的欄位的單字元字串。預設為'"'
。如果 quoting 設定為QUOTE_NONE
,可以設定為None
> 以防止轉義'"'
。在 3.11 版本發生變更: 不允許空的 quotechar。
- Dialect.quoting¶
控制 writer 何時生成引號以及 reader 何時識別引號。它可以是任何 QUOTE_* 常量,如果 quotechar 不是
None
,則預設為QUOTE_MINIMAL
,否則預設為QUOTE_NONE
。
Reader 物件¶
Reader 物件(DictReader
例項和由 reader()
函式返回的物件)具有以下公共方法
- csvreader.__next__()¶
返回 reader 的可迭代物件的下一行,格式為列表(如果物件是從
reader()
返回的)或字典(如果它是DictReader
例項),並根據當前的Dialect
進行解析。通常你應該以next(reader)
> 的形式呼叫它。
Reader 物件具有以下公共屬性
- csvreader.dialect¶
解析器使用的方言的只讀描述。
- csvreader.line_num¶
從源迭代器讀取的行數。這與返回的記錄數不同,因為記錄可以跨越多行。
DictReader 物件具有以下公共屬性
- DictReader.fieldnames¶
如果在建立物件時未作為引數傳遞,此屬性會在首次訪問或從檔案中讀取第一條記錄時初始化。
Writer 物件¶
writer
物件(DictWriter
例項和由 writer()
函式返回的物件)具有以下公共方法。對於 writer
物件,row 必須是字串或數字的可迭代物件;對於 DictWriter
物件,row 必須是將欄位名對映到字串或數字的字典(透過先傳遞給 str()
)。請注意,複數會用括號括起來寫入。這可能會給其他讀取 CSV 檔案的程式帶來一些問題(假設它們支援複數)。
- csvwriter.writerow(row, /)¶
將 row 引數寫入 writer 的檔案物件,並根據當前的
Dialect
進行格式化。返回底層檔案物件的 write 方法呼叫的返回值。在 3.5 版本發生變更: 增加了對任意可迭代物件的支援。
- csvwriter.writerows(rows, /)¶
將 rows(一個如上所述的 row 物件的可迭代物件)中的所有元素寫入 writer 的檔案物件,並根據當前方言進行格式化。
Writer 物件具有以下公共屬性
- csvwriter.dialect¶
writer 使用的方言的只讀描述。
DictWriter 物件具有以下公共方法
- DictWriter.writeheader()¶
將一行帶有欄位名(在建構函式中指定)的資料寫入 writer 的檔案物件,並根據當前方言進行格式化。返回內部使用的
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 檔案進行讀取,因此預設情況下,檔案將使用系統預設編碼解碼為 unicode(參見 locale.getencoding()
)。要使用不同的編碼解碼檔案,請使用 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')
一個更高階的 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(f'file {filename}, line {reader.line_num}: {e}')
雖然該模組不直接支援解析字串,但可以很容易地實現
import csv
for row in csv.reader(['one,two,three']):
print(row)
腳註