Featured image of post 從零開始學Python (16) — 檔案讀寫:妳出現在我詩的每一頁(中)

從零開始學Python (16) — 檔案讀寫:妳出現在我詩的每一頁(中)

Day 16 檔案讀寫:妳出現在我詩的每一頁(中)

註:本篇文章同步刊載於iT邦幫忙,為鐵人賽之系列文章。
https://ithelp.ithome.com.tw/articles/10245278

上一回我們簡單介紹了如何讀一般的文字檔案,
那如果格式比較特別呢?
通常狀況下,會需要特別格式的原因,
是因為它代表了一段「資料」,
也就是說,讀取不同格式的檔案,
基本上就是在透過大家約定好的格式方法,
將資料從檔案中按規則讀出來。

以Python來說,最常見被拿來儲存的格式有CSV, XML, YAML, JSON等,
接下來的兩篇文章中,讓我們來分別介紹CSV和JSON吧!

CSV

CSV是相當淺顯易懂的格式,
如果讀者有在用Excel時,存檔時就會看到有CSV的選項。
一般而言,一個CSV檔案中,
每一個**row(列)的不同單位常以逗號分隔,
(也有用tab鍵的,相當於’\t’)
column(行)**的計算則是以換行符號為準。
(Unix/Mac系統使用’\n’,Windows系統則用’\r\n’)
註:中國和台灣在指稱列跟行時是剛好相反的,容易搞混。
如果沒有特別需求的話,直接使用row/column來對應稱呼橫向/直向就好。

還記得我們之前的三個同學的成績嗎?

1
2
3
ming = Student('阿明', {'數學':55, '英文':70, '物理':55})
mei = Student('小美', {'數學':90, '英文':88, '物理':100})
howhow = Student('HowHow', {'數學':80, '英文':60, '物理':40})

如果今天我們要使用csv的方式將這個成績記錄起來,
我們可能會考慮寫成這樣:

1
2
3
4
姓名, 數學, 英文, 物理
阿明,   55,  70,   55
小美,   90,  88,  100
HowHow, 80,  60,   40

那麼,我們怎麼存放到csv中呢?
Python中有內建一個csv 的模組,
我們可以用其writer的writerow()或writerows()來處理:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import csv
with open('student.csv', 'w', newline='') as f:
    csvw = csv.writer(f, delimiter=' ') # delimiter預設是',',可以自己更改
    csvw.writerow(['姓名', '數學', '英文', '物理']) # 一次寫一個row
    students = [
        ['阿明',   55,  70,   55],
        ['小美',   90,  88,  100],
        ['HowHow', 80,  60,   40]
    ]
    csvw.writerows(students) # 一次寫多個rows

(delimiter是指分隔符號)
特別留意,在使用csv來處理時,開啟檔案請務必設置參數, newline=’’,
以避免掉作業系統對於換行的處理不同的問題。
(全部交由csv writer來處理就好!)
其結果應該如下:

接著我們嘗試將其讀回來,
這時候就要改成用csv的reader,
reader的部分比較簡單,我們可以用for…in…的方式來按row取出:

1
2
3
4
import csv
with open('student.csv', 'r') as f:
    csvr = csv.reader(f, delimiter=' ') #
    student_from_file = [row for row in csvr]
1
print(student_from_file)

讀出來的結果如下。

1
2
C:\Users\Desolve>python fromzero.py
[['姓名', '數學', '英文', '物理'], ['阿明', '55', '70', '55'], ['小美', '90', '88', '100'], ['HowHow', '80', '60', '40']]

那麼,如果是要處理字典呢?
我們可以使用DictWriter/DictReader
假定我們已經有一段關於三名學生的字典:
{‘姓名’:’阿明’, ‘數學’:55, ‘英文’:70, ‘物理’:55}
{‘姓名’:’小美’, ‘數學’:90, ‘英文’:88, ‘物理’:100}
{‘姓名’:’HowHow’,’數學’:80, ‘英文’:60, ‘物理’:40}
我們可以用如下的方式來寫入:

1
import csv
1
2
3
4
5
6
7
with open('student_dic.csv', 'w', newline='') as f:
    field = ['姓名', '數學', '英文', '物理'] # 第一個row做為欄位名稱
    csvw = csv.DictWriter(f, delimiter=' ', fieldnames=field)
    csvw.writeheader()
    csvw.writerow({'姓名':'阿明', '數學':55, '英文':70, '物理':55})
    csvw.writerow({'姓名':'小美', '數學':90, '英文':88, '物理':100})
    csvw.writerow({'姓名':'HowHow','數學':80, '英文':60, '物理':40})
1
2
3
4
5
with open('student_dic.csv', 'r') as f:
    # DictReader將第一個row當做欄位名稱,所以就省略了
    csvr = csv.DictReader(f, delimiter=' ')
    student = [row for row in csvr]
    print(student)

讀出來應該如下:

1
2
C:\Users\Desolve>python fromzero.py
[{'姓名': '阿明', '數學': '55', '英文': '70', '物理': '55'}, {'姓名': '小美', '數學': '90', '英文': '88', '物理': '100'}, {'姓名': 'HowHow', '數學': '80', '英文': '60', '物理': '40'}]

上面敘述的所有範例,在讀寫未知的檔案時,
我們都無法保證是否csv能夠正常運作,
所以最好還是用一下try…except的方法,
對於csv模組傳出的錯誤,
可以使用try …**except csv.Error as e:**來接取。

還吃得消嗎?加油!
那我們下一篇再來談談JSON囉!
明天見~

工商時間:

抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)
Python Taiwan的連結第100篇的文章 底下,
公開分享到你的臉書、按讚該篇文章、並留言告訴我說,
「你最喜歡這一整個系列的哪一篇?為什麼?」或
「除了從LeetCode學演算法系列以外,
你還想要看到關於什麼方向的文章?」

超過20則留言的話 (有完成以上步驟的才算),我們就抽一組
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」
課程的免費兌換券進行贈送!

期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)

容筆者工商一下,
「從Leetcode學演算法|進階篇」 開放預購啦!
這次選了40道難度加深的LeetCode題目,
同樣也會細部解說對應的技巧及須要掌握的演算法!
同時這次購買進階篇的話,
額外還加贈**「從Leetcode學演算法|面試篇」** !
當中包含了面試準備須知分享及訪談國內外不同經驗的工程師
讓你不論是想走前端/後端/一般軟工 或者是想找國外的工作
初學想轉職 還是正在工作 ,都能夠從中得到收穫呦!
有興趣的朋友可以使用下面的早鳥優惠~
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」
https://bit.ly/advleetcode

「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠:
https://bit.ly/allleetcode

共發表了 171 篇文章 ‧ 總計 311.6k
使用 Hugo 建立
主題 StackJimmy 設計