1. 程式人生 > >python的CSV模組

python的CSV模組

開發環境:Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 64 bit (AMD64)] on win32

自序

也許你會說,我為什麼要學習使用CSV模組呢?沒有CSV模組我一樣可以解析操作CSV檔案,比如下面這種程式碼:

1
2
3
4
5
with open('stocks.csv') as f:
for line in f:
    row = line.split(',')
    # process row
    ...

使用這種方式的一個缺點就是你仍然需要去處理一些棘手的細節問題。比如,如果某些欄位值被引號包圍,你不得不去除這些引號。另外,如果一個被引號包圍的欄位碰巧含有一個逗號,那麼程式就會因為產生一個錯誤而停止。

預設情況下,CSV庫可識別Microsoft Excel所使用的CSV編碼規則。這或許也是最常見的形式,並且也會給你帶來最好的相容性。然而,如果你檢視CSV的文件,就會發現有很多種方法將它應用到其他編碼格式上(如修改分隔字元等,用Tab分隔)。所以你應該總是優先選擇CSV模組分割或解析CSV資料。

CSV格式簡介

逗號分隔值(Comma-Separated ValuesCSV,有時也稱為字元分隔值,因為分隔字元也可以不是逗號),其檔案以純文字形式儲存表格資料(數字和文字)。純文字意味著該檔案是一個字元序列,不含必須像二進位制數字那樣被解讀的資料。CSV檔案由任意數目的記錄組成,記錄間以某種換行符分隔;每條記錄由欄位組成,欄位間的分隔符是其它字元或字串,最常見的是逗號或製表符。通常,所有記錄都有完全相同的欄位序列。

CSV檔案注意點

如果你正在讀取CSV資料並將它們轉換為命名元組,需要注意對列名進行合法性認證。一個CSV格式檔案有一個包含非法識別符號的列頭行,這樣最終會導致在建立一個命名元組時產生一個ValueError異常而失敗。為了解決這問題,你可能不得不先去修正列標題。

1
2
3
4
5
6
7
8
9
import re
with open('stock.csv') as f:
    f_csv = csv.reader(f)
    headers = [ re.sub('[^a-zA-Z_]', '_', h) for h in next(f_csv) ]
    Row = namedtuple('Row'
, headers)
for r in f_csv: row = Row(*r) # Process row ...

還有重要的一點需要強調的是,CSV產生的資料都是字串型別的,它不會做任何其他型別的轉換。如果你需要做這樣的型別轉換,你必須自己手動去實現。

CSV模組操作示例

輸入檔案:stocks.csv

1
2
3
4
5
6
7
Symbol,Price,Date,Time,Change,Volume
"AA",39.48,"6/11/2007","9:36am",-0.18,181800
"AIG",71.38,"6/11/2007","9:36am",-0.15,195500
"AXP",62.58,"6/11/2007","9:36am",-0.46,935000
"BA",98.31,"6/11/2007","9:36am",+0.12,104800
"C",53.08,"6/11/2007","9:36am",-0.25,360900
"CAT",78.29,"6/11/2007","9:36am",-0.23,225400

輸出檔案:dest.csv

1
2
3
4
Symbol,Price,Date,Time,Change,Volume
AA,39.48,6/11/2007,9:36am,-0.18,181800
AIG,71.38,6/11/2007,9:36am,-0.15,195500
AXP,62.58,6/11/2007,9:36am,-0.46,935000

程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#!/usr/bin/python
# coding: UTF-8
"""
Created on 2015/9/30  14:55
@author: 'WX'
"""
from collections import namedtuple
import csv

if __name__ == "__main__":
    fileName = 'stocks.csv'
    writeFileName = 'dest.csv'
    with open(fileName) as f:
        reader = csv.reader(f)
        headers = next(reader)
        print("使用下標進行訪問")
        for row in reader:
            # 可以使用下標進行訪問,row是一個元組
            length = len(row)
            for i in range(length):
                print(row[i], end='\t')
            print()

        print('------------------------------------------------')
    with open(fileName) as f:
        # 使用命名元組訪問
        reader = csv.reader(f)
        headers = next(reader)
        Row = namedtuple('Row', headers)
        print("使用命名元組進行訪問")
        for r in reader:
            row = Row(*r)
            # 這時候就可以使用首行的列名來進行訪問了
            line = '%s\t%s\t%s\t%s\t%s\t%s' % (row.Symbol, row.Price, row.Date, row.Time, row.Change, row.Volume)
            print(line)
        print('------------------------------------------------')

    with open(fileName) as f:
        # 將內容讀取到字典序列中,然後用key去讀取
        dict_reader = csv.DictReader(f)
        print("使用字典序列進行訪問")
        for row in dict_reader:
            line = '%s\t%s\t%s\t%s\t%s\t%s' % (
                row['Symbol'], row['Price'], row['Date'], row['Time'], row['Change'], row['Volume'])
            print(line)
    print('------------------------------------------------')

    print("使用元組方式寫入,SUCCESS!")
    with open(writeFileName, mode='w', newline='') as wf:
        headers = ['Symbol', 'Price', 'Date', 'Time', 'Change', 'Volume']
        rows = [('AA', 39.48, '6/11/2007', '9:36am', -0.18, 181800),
                ('AIG', 71.38, '6/11/2007', '9:36am', -0.15, 195500),
                ('AXP', 62.58, '6/11/2007', '9:36am', -0.46, 935000),
                ]
        writer = csv.writer(wf)
        writer.writerow(headers)
        writer.writerows(rows)
    print("使用字典方式寫入,SUCCESS!")
    # 在Windows平臺需要指定newline='',否則在兩行內容之間會多出一行空行
    with open(writeFileName, mode='w', newline='') as wf:
        headers = ['Symbol', 'Price', 'Date', 'Time', 'Change', 'Volume']
        rows = [{'Symbol': 'AA', 'Price': 39.48, 'Date': '6/11/2007',
                 'Time': '9:36am', 'Change': -0.18, 'Volume': 181800},
                {'Symbol': 'AIG', 'Price': 71.38, 'Date': '6/11/2007',
                 'Time': '9:36am', 'Change': -0.15, 'Volume': 195500},
                {'Symbol': 'AXP', 'Price': 62.58, 'Date': '6/11/2007',
                 'Time': '9:36am', 'Change': -0.46, 'Volume': 935000}, ]
        writer = csv.DictWriter(wf, headers)
        writer.writeheader()
        writer.writerows(rows)
    # 更換一種分隔符寫入檔案
    with open(writeFileName, mode='w', newline='') as wf:
        headers = ['Symbol', 'Price', 'Date', 'Time', 'Change', 'Volume']
        rows = [('AA', 39.48, '6/11/2007', '9:36am', -0.18, 181800),
                ('AIG', 71.38, '6/11/2007', '9:36am', -0.15, 195500),
                ('AXP', 62.58, '6/11/2007', '9:36am', -0.46, 935000),
                ]
        writer = csv.writer(wf, delimiter=';')
        writer.writerow(headers)
        writer.writerows(rows)
    print("使用分好作為分隔符寫入,SUCCESS!")

控制檯輸出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
C:\Python34\python.exe E:/workspaces/Python3/edu/shu/python/shumo/CsvUtil.py
使用下標進行訪問
AA    39.48    6/11/2007    9:36am    -0.18    181800
AIG    71.38    6/11/2007    9:36am    -0.15    195500
AXP    62.58    6/11/2007    9:36am    -0.46    935000
BA    98.31    6/11/2007    9:36am    +0.12    104800
C    53.08    6/11/2007    9:36am    -0.25    360900
CAT    78.29    6/11/2007    9:36am    -0.23    225400
------------------------------------------------
使用命名元組進行訪問
AA    39.48    6/11/2007    9:36am    -0.18    181800
AIG    71.38    6/11/2007    9:36am    -0.15    195500
AXP    62.58    6/11/2007    9:36am    -0.46    935000
BA    98.31    6/11/2007    9:36am    +0.12    104800
C    53.08    6/11/2007    9:36am    -0.25    360900
CAT    78.29    6/11/2007    9:36am    -0.23    225400
------------------------------------------------
使用字典序列進行訪問
AA    39.48    6/11/2007    9:36am    -0.18    181800
AIG    71.38    6/11/2007    9:36am    -0.15    195500
AXP    62.58    6/11/2007    9:36am    -0.46    935000
BA    98.31    6/11/2007    9:36am    +0.12    104800
C    53.08    6/11/2007    9:36am    -0.25    360900
CAT    78.29    6/11/2007    9:36am    -0.23    225400
------------------------------------------------
使用元組方式寫入,SUCCESS!
使用字典方式寫入,SUCCESS!

Process finished with exit code 0