---
# System prepended metadata

title: Python CSV
tags: [python]

---

# Python CSV

這裡介紹如何在 Python 中使用 `csv` 模組，讀取與寫入逗點分隔檔。

逗點分隔（Comma-Separated Values，簡稱 csv）是一種簡單的文字檔格式，以逗號分隔不同欄位的資料，很多軟體在儲存與交換表格資料時都支援這樣的格式。

在 Python 中若要讀取或產生 csv 的檔案，可以使用內建的 `csv` 模組，以下是使用方式以及範例程式碼。



## 讀取 CSV 檔案

假設我們有一個 csv 檔案 `iris.csv`，其內容如下：

```
sepal_length,sepal_width,petal_length,petal_width,species
5.1,3.5,1.4,0.2,setosa
4.9,3,1.4,0.2,setosa
4.7,3.2,1.3,0.2,setosa
4.6,3.1,1.5,0.2,setosa
[略]
```

我們可以使用下面這段程式碼將這個 csv 檔的內容讀取出來：

```
import csv

# 開啟 CSV 檔案
with open('iris.csv', newline='') as csvfile:

  # 讀取 CSV 檔案內容
  rows = csv.reader(csvfile)

  # 以迴圈輸出每一列
  for row in rows:
    print(row)
```

我們使用 `csv.reader` 讀取出來的 `rows` 會是一個二維的 list，裡面就是整張表格的資料，這裡我們把每一列的 list 直接輸出，執行後會像這樣：

```
['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species']
['5.1', '3.5', '1.4', '0.2', 'setosa']
['4.9', '3', '1.4', '0.2', 'setosa']
['4.7', '3.2', '1.3', '0.2', 'setosa']
['4.6', '3.1', '1.5', '0.2', 'setosa']
[略]
```

這裡在開啟 csv 檔案時加上了 `newline=''` 參數，這是為了讓資料中包含的換行字元可以正確被解析，所以建議在讀取 csv 檔案時都固定加入這個參數。

### 指定分隔字元

如果資料欄位之間的分隔字元不是使用預設的逗號，而是其他字元的話，在讀取時就要自行指定欄位的分隔字元。假設我們要讀取 Linux 的 `/etc/passwd` 這個檔案，資料如下：

```
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
[略]
```

這個檔案內容的各個欄位是以冒號（`:`）來分隔的，我們可以使用以下這段程式碼來讀取：

```
import csv
with open('/etc/passwd', newline='') as csvfile:

  # 以冒號分隔欄位，讀取檔案內容
  rows = csv.reader(csvfile, delimiter=':')

  for row in rows:
    print(row)
```

輸出如下：

```
['root', 'x', '0', '0', 'root', '/root', '/bin/bash']
['daemon', 'x', '1', '1', 'daemon', '/usr/sbin', '/usr/sbin/nologin']
['bin', 'x', '2', '2', 'bin', '/bin', '/usr/sbin/nologin']
['sys', 'x', '3', '3', 'sys', '/dev', '/usr/sbin/nologin']
['sync', 'x', '4', '65534', 'sync', '/bin', '/bin/sync']
[略]
```

### 讀取成 Dictionary

我們也可以將 csv 檔案的內容讀取進來之後，轉為 Python 的 dictionary 格式，這樣在存取各定資料時會方便一些：

```
import csv
with open('iris.csv', newline='') as csvfile:

  # 讀取 CSV 檔內容，將每一列轉成一個 dictionary
  rows = csv.DictReader(csvfile)

  # 以迴圈輸出指定欄位
  for row in rows:
    print(row['sepal_length'], row['species'])
```

這個例子中我們使用以 `csv.DictReader` 來讀取 CSV 檔案的內容，它會自動把第一列（row）當作欄位的名稱，將第二列以後的每一列轉為 dictionary，這樣我們就可以使用欄位的名稱來存取資料。執行後的輸出會像這樣：

```
5.1 setosa
4.9 setosa
4.7 setosa
4.6 setosa
5 setosa
```



## 寫入 CSV 檔案

如果我們在程式中產生了表格的資料，想要儲存為 csv 檔案，可以使用以下這段程式碼：

```
import csv

# 開啟輸出的 CSV 檔案
with open('output.csv', 'w', newline='') as csvfile:
  # 建立 CSV 檔寫入器
  writer = csv.writer(csvfile)

  # 寫入一列資料
  writer.writerow(['姓名', '身高', '體重'])

  # 寫入另外幾列資料
  writer.writerow(['令狐沖', 175, 60])
  writer.writerow(['岳靈珊', 165, 57])
```

產生的 `output.csv` 檔案內容會像這樣：

```
姓名,身高,體重
令狐沖,175,60
岳靈珊,165,57
```

### 指定分隔字元

輸出 csv 檔案時也可以自行指定欄位的分隔字元，例如：

```
import csv
with open('output.csv', 'w', newline='') as csvfile:

  # 以空白分隔欄位，建立 CSV 檔寫入器
  writer = csv.writer(csvfile, delimiter=' ')

  writer.writerow(['姓名', '身高', '體重'])
  writer.writerow(['令狐沖', 175, 60])
  writer.writerow(['岳靈珊', 165, 57])
```

輸出的 `output.csv` 檔案內容會變成這樣：

```
姓名 身高 體重
令狐沖 175 60
岳靈珊 165 57
```

### 一次寫入二維表格

如果我們的資料是已經整理好的二維表格，也可以一次就把整張表格寫進 csv 檔案中：

```
import csv

# 二維表格
table = [
    ['姓名', '身高', '體重'],
    ['令狐沖', 175, 60],
    ['岳靈珊', 165, 57]
]

with open('output.csv', 'w', newline='') as csvfile:
  writer = csv.writer(csvfile)

  # 寫入二維表格
  writer.writerows(table)
```

這樣產生的 csv 檔案也會跟上面的例子相同。

### 寫入 Dictionary

如果我們在 Python 中的資料格式是 dictionary，也可以使用 `csv.DictWriter` 直接將 dictionary 寫入 csv 檔案中：

```
import csv
with open('output.csv', 'w', newline='') as csvfile:
  # 定義欄位
  fieldnames = ['姓名', '身高', '體重']

  # 將 dictionary 寫入 CSV 檔
  writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

  # 寫入第一列的欄位名稱
  writer.writeheader()

  # 寫入資料
  writer.writerow({'姓名': '令狐沖', '身高': 175, '體重': 60})
  writer.writerow({'姓名': '岳靈珊', '身高': 165, '體重': 57})
```

此範例輸出的檔案內容也跟上面的例子相同。