翻譯:《實(shí)用的Python編程》01_06_Files
目錄| 上一節(jié)(1.5 列表) | 下一節(jié) (1.7 函數(shù))
1.6 文件管理
大多數(shù)的程序需要從某處讀取輸入。本節(jié)討論文件訪問。
文件輸入和輸出
打開一個(gè)文件:
f = open('foo.txt', 'rt') # Open for reading (text)
g = open('bar.txt', 'wt') # Open for writing (text)
讀取所有的數(shù)據(jù):
data = f.read()
# Read only up to 'maxbytes' bytes
data = f.read([maxbytes])
寫入一些文本:
g.write('some text')
當(dāng)你完成操作后,關(guān)閉文件:
f.close()
g.close()
文件應(yīng)該被正確的關(guān)閉,這是很容易忘記的一個(gè)步驟。因此,首選方法是像下面這樣使用 with 語句:
with open(filename, 'rt') as file:
# Use the file `file`
...
# No need to close explicitly
...statements
當(dāng)控制流離開縮進(jìn)的代碼塊時(shí),這將會(huì)自動(dòng)關(guān)閉文件。
讀取文件數(shù)據(jù)的習(xí)慣用法
以字符串的形式一次性讀取整個(gè)文件:
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
寫入文件的習(xí)慣用法
寫入字符串?dāng)?shù)據(jù):
with open('outfile', 'wt') as out:
out.write('Hello World\n')
...
重定向 print() 函數(shù):
with open('outfile', 'wt') as out:
print('Hello World', file=out)
...
練習(xí)
本練習(xí)依賴于 Data/portfolio.csv 文件。該文件由一行一行的關(guān)于股票投資組合的信息構(gòu)成。假定你是在 practical-python/Work/ 目錄下進(jìn)行操作。如果你不確定自己所在的目錄,你可以通過執(zhí)行以下操作找出 Python 運(yùn)行的目錄:
>>> import os
>>> os.getcwd()
'/Users/beazley/Desktop/practical-python/Work' # Output vary
>>>
練習(xí) 1.26: 文件預(yù)覽
首先,嘗試以字符串的形式一次性讀取整個(gè)文件:
>>> 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
>>>
在上面的示例中,應(yīng)注意 Python 有兩種輸出模式。在第一種模式下,你在提示符后輸入 data,Python 向你展示包含引號(hào)和轉(zhuǎn)義碼的原始字符串。當(dāng)你輸入 print(data)時(shí),你獲得真正的字符串的格式化輸出。
一次性讀取文件很簡單,但這通常不是最恰當(dāng)?shù)淖x取文件方式——尤其是當(dāng)文件碰巧很大或者文件包含要一次性處理的文本行時(shí)。
要逐行讀取文件,可以像下面這樣使用 for 循環(huán):
>>> 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
...
>>>
當(dāng)你像上面展示的那樣使用此代碼時(shí),它會(huì)讀取文件的每一行,直到到達(dá)文件末尾。在文件末尾,循環(huán)會(huì)停止。
在某些特定的情況下,你可能想要手動(dòng)的讀取或者跳過某一行文本(例如,可能你想跳過列標(biāo)題的第一行):
>>> 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() 函數(shù)返回文件中的下一行文本。如果你反復(fù)調(diào)用該函數(shù),將會(huì)獲得連續(xù)的行。但是,如你所知,for 循環(huán)已經(jīng)使用 next() 函數(shù)獲取數(shù)據(jù)了。所以,通常情況下,除非你像上面展示的那樣試圖顯式跳過或者讀取一行,否則,不要直接調(diào)用 next() 函數(shù)。
一旦讀取文件的各行,你就可以開始執(zhí)行更多的操作,例如拆分。
示例,嘗試以下操作:
>>> 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()
注意:在這些示例中,因?yàn)闆]有使用 with 語句,所以 f.close() 被顯式的調(diào)用。
練習(xí) 1.27: 讀取數(shù)據(jù)文件
現(xiàn)在你已經(jīng)知道如何讀取文件,讓我們編寫一個(gè)程序來執(zhí)行簡單的計(jì)算。
portfolio.csv 文件里面的列對(duì)應(yīng)股票的名稱,股票的數(shù)量以及單支股票持有的購買價(jià)格。編寫一個(gè)名為 pcost.py 的程序來打開這個(gè)文件,讀取所有的行并且計(jì)算在所有的股票投資組合中花費(fèi)多少錢來購買這些股份。
提示:要將字符串轉(zhuǎn)為整數(shù),使用 int() 函數(shù)。要將字符串轉(zhuǎn)為浮點(diǎn)數(shù),使用 float() 函數(shù)。
你的程序應(yīng)該打印如下輸出:
Total cost 44671.15
練習(xí) 1.28: 其它類型的“文件"
如果你想讀取非文本文件(如 gzip 壓縮的數(shù)據(jù)文件)怎么辦?雖然內(nèi)建 open() 函數(shù)在這里幫不了你了,但是 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' 文件模式至關(guān)重要。如果你忘記使用它,你將會(huì)得到字節(jié)字符串而不是通常的文本字符串。
說明: 我們不應(yīng)該為此使用 Pandas 嗎?
數(shù)據(jù)科學(xué)家很快指出,諸如 Pandas 這樣的庫已經(jīng)具有讀取 CSV 文件的函數(shù),為什么不使用 Pandas 呢?的確如此——而且效果也很好。但是,這不是一門有關(guān)學(xué)習(xí) Pandas 的課程,讀取文件是一個(gè)比讀取 CSV 文件更普遍的問題。我們使用 CSV 文件做例子的主要原因是:它是大多數(shù)編碼人員熟悉的格式,并且相對(duì)易于直接使用——在讀取 CSV 文件的過程中,闡明了許多 Python 特性。所以,當(dāng)你回到工作中,請(qǐng)務(wù)必使用 Pandas。但是,在本課程剩下部分,我們將會(huì)繼續(xù)使用標(biāo)準(zhǔn)的 Python 函數(shù)。
浙公網(wǎng)安備 33010602011771號(hào)