翻譯:《實用的Python編程》01_06_Files
- 2021 年 2 月 18 日
- 筆記
- Python, 實用的Python編程
目錄| 上一節(1.5 列表) | 下一節 (1.7 函數)
1.6 文件管理
大多數的程式需要從某處讀取輸入。本節討論文件訪問。
文件輸入和輸出
打開一個文件:
f = open('foo.txt', 'rt') # Open for reading (text)
g = open('bar.txt', 'wt') # Open for writing (text)
讀取所有的數據:
data = f.read()
# Read only up to 'maxbytes' bytes
data = f.read([maxbytes])
寫入一些文本:
g.write('some text')
當你完成操作後,關閉文件:
f.close()
g.close()
文件應該被正確的關閉,這是很容易忘記的一個步驟。因此,首選方法是像下面這樣使用 with
語句:
with open(filename, 'rt') as file:
# Use the file `file`
...
# No need to close explicitly
...statements
當控制流離開縮進的程式碼塊時,這將會自動關閉文件。
讀取文件數據的習慣用法
以字元串的形式一次性讀取整個文件:
with open('foo.txt', 'rt') as file:
data = file.read()
# `data` is a string with all the text in `foo.txt`
通過迭代逐行讀取文件:
with open(filename, 'rt') as file:
for line in file:
# Process the line
寫入文件的習慣用法
寫入字元串數據:
with open('outfile', 'wt') as out:
out.write('Hello World\n')
...
重定向 print() 函數:
with open('outfile', 'wt') as out:
print('Hello World', file=out)
...
練習
本練習依賴於 Data/portfolio.csv
文件。該文件由一行一行的關於股票投資組合的資訊構成。假定你是在 practical-python/Work/
目錄下進行操作。如果你不確定自己所在的目錄,你可以通過執行以下操作找出 Python 運行的目錄:
>>> import os
>>> os.getcwd()
'/Users/beazley/Desktop/practical-python/Work' # Output vary
>>>
練習 1.26: 文件預覽
首先,嘗試以字元串的形式一次性讀取整個文件:
>>> with open('Data/portfolio.csv', 'rt') as f:
data = f.read()
>>> data
'name,shares,price\n"AA",100,32.20\n"IBM",50,91.10\n"CAT",150,83.44\n"MSFT",200,51.23\n"GE",95,40.37\n"MSFT",50,65.10\n"IBM",100,70.44\n'
>>> print(data)
name,shares,price
"AA",100,32.20
"IBM",50,91.10
"CAT",150,83.44
"MSFT",200,51.23
"GE",95,40.37
"MSFT",50,65.10
"IBM",100,70.44
>>>
在上面的示例中,應注意 Python 有兩種輸出模式。在第一種模式下,你在提示符後輸入 data
,Python 向你展示包含引號和轉義碼的原始字元串。當你輸入 print(data)
時,你獲得真正的字元串的格式化輸出。
一次性讀取文件很簡單,但這通常不是最恰當的讀取文件方式——尤其是當文件碰巧很大或者文件包含要一次性處理的文本行時。
要逐行讀取文件,可以像下面這樣使用 for 循環:
>>> with open('Data/portfolio.csv', 'rt') as f:
for line in f:
print(line, end='')
name,shares,price
"AA",100,32.20
"IBM",50,91.10
...
>>>
當你像上面展示的那樣使用此程式碼時,它會讀取文件的每一行,直到到達文件末尾。在文件末尾,循環會停止。
在某些特定的情況下,你可能想要手動的讀取或者跳過某一行文本(例如,可能你想跳過列標題的第一行):
>>> f = open('Data/portfolio.csv', 'rt')
>>> headers = next(f)
>>> headers
'name,shares,price\n'
>>> for line in f:
print(line, end='')
"AA",100,32.20
"IBM",50,91.10
...
>>> f.close()
>>>
next()
函數返迴文件中的下一行文本。如果你反覆調用該函數,將會獲得連續的行。但是,如你所知,for
循環已經使用 next()
函數獲取數據了。所以,通常情況下,除非你像上面展示的那樣試圖顯式跳過或者讀取一行,否則,不要直接調用 next()
函數。
一旦讀取文件的各行,你就可以開始執行更多的操作,例如拆分。
示例,嘗試以下操作:
>>> f = open('Data/portfolio.csv', 'rt')
>>> headers = next(f).split(',')
>>> headers
['name', 'shares', 'price\n']
>>> for line in f:
row = line.split(',')
print(row)
['"AA"', '100', '32.20\n']
['"IBM"', '50', '91.10\n']
...
>>> f.close()
注意:在這些示例中,因為沒有使用 with
語句,所以 f.close()
被顯式的調用。
練習 1.27: 讀取數據文件
現在你已經知道如何讀取文件,讓我們編寫一個程式來執行簡單的計算。
portfolio.csv
文件裡面的列對應股票的名稱,股票的數量以及單支股票持有的購買價格。編寫一個名為 pcost.py
的程式來打開這個文件,讀取所有的行並且計算在所有的股票投資組合中花費多少錢來購買這些股份。
提示:要將字元串轉為整數,使用 int()
函數。要將字元串轉為浮點數,使用 float()
函數。
你的程式應該列印如下輸出:
Total cost 44671.15
練習 1.28: 其它類型的「文件”
如果你想讀取非文本文件(如 gzip 壓縮的數據文件)怎麼辦?雖然內建 open()
函數在這裡幫不了你了,但是 Python 提供的 gzip
模組可以讀取 gzip 文件。
試試看:
>>> import gzip
>>> with gzip.open('Data/portfolio.csv.gz', 'rt') as f:
for line in f:
print(line, end='')
... look at the output ...
>>>
注意:此處包含 'rt'
文件模式至關重要。如果你忘記使用它,你將會得到位元組字元串而不是通常的文本字元串。
說明: 我們不應該為此使用 Pandas 嗎?
數據科學家很快指出,諸如 Pandas 這樣的庫已經具有讀取 CSV 文件的函數,為什麼不使用 Pandas 呢?的確如此——而且效果也很好。但是,這不是一門有關學習 Pandas 的課程,讀取文件是一個比讀取 CSV 文件更普遍的問題。我們使用 CSV 文件做例子的主要原因是:它是大多數編碼人員熟悉的格式,並且相對易於直接使用——在讀取 CSV 文件的過程中,闡明了許多 Python 特性。所以,當你回到工作中,請務必使用 Pandas。但是,在本課程剩下部分,我們將會繼續使用標準的 Python 函數。
目錄| 上一節(1.5 列表) | 下一節 (1.7 函數)
註:完整翻譯見 //github.com/codists/practical-python-zh