一文搞定Python讀取文件的全部知識
↑?關注 + 星標?,每天學Python新技能
后臺回復【大禮包】送你Python自學大禮包
文件是無處不在的,無論我們使用哪種編程語言,處理文件對于每個程序員都是必不可少的
文件處理是一種用于創(chuàng)建文件、寫入數據和從中讀取數據的過程,Python 擁有豐富的用于處理不同文件類型的包,從而使得我們可以更加輕松方便的完成文件處理的工作
本文大綱:
使用上下文管理器打開文件 Python 中的文件讀取模式 讀取 text 文件 讀取 CSV 文件 讀取 JSON 文件

打開文件
在訪問文件的內容之前,我們需要打開文件。Python 提供了一個內置函數可以幫助我們以不同的模式打開文件。open() 函數接受兩個基本參數:文件名和模式
默認模式是“r”,它以只讀方式打開文件。這些模式定義了我們如何訪問文件以及我們如何操作其內容。open() 函數提供了幾種不同的模式,我們將在后面逐一討論
下面我們通過 ’Python 之禪‘ 文件來進行后面的討論學習
f?=?open('zen_of_python.txt',?'r')
print(f.read())
f.close()
Output:
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
...在上面的代碼中,open() 函數以只讀模式打開文本文件,這允許我們從文件中獲取信息而不能更改它。在第一行,open() 函數的輸出被賦值給一個代表文本文件的對象 f,在第二行中,我們使用 read() 方法讀取整個文件并打印其內容,close() 方法在最后一行關閉文件。需要注意,我們必須始終在處理完打開的文件后關閉它們以釋放我們的計算機資源并避免引發(fā)異常
在 Python 中,我們可以使用 with 上下文管理器來確保程序在文件關閉后釋放使用的資源,即使發(fā)生異常也是如此
with?open('zen_of_python.txt')?as?f:
????print(f.read())
Output:
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
...上面的代碼使用 with 語句創(chuàng)建了一個上下文,并綁定到變量 f ,所有文件對象方法都可以通過該變量訪問文件對象。read() 方法在第二行讀取整個文件,然后使用 print() 函數輸出文件內容
當程序到達 with 語句塊上下文的末尾時,它會關閉文件以釋放資源并確保其他程序可以正常調用它們。通常當我們處理不再需要使用的,需要立即關閉的對象(例如文件、數據庫和網絡連接)時,強烈推薦使用 with 語句
這里需要注意的是,即使在退出 with 上下文管理器塊之后,我們也可以訪問 f 變量,但是該文件是已關閉狀態(tài)。讓我們嘗試一些文件對象屬性,看看變量是否仍然存在并且可以訪問:
print("Filename?is?'{}'.".format(f.name))
if?f.closed:
????print("File?is?closed.")
else:
????print("File?isn't?closed.")
Output:
Filename is 'zen_of_python.txt'.
File is closed.但是此時是不可能從文件中讀取內容或寫入文件的,關閉文件時,任何訪問其內容的嘗試都會導致以下錯誤:
f.read()
Output:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_9828/3059900045.py in
----> 1 f.read()
ValueError: I/O operation on closed file.Python 中的文件讀取模式
正如我們在前面提到的,我們需要在打開文件時指定模式。下表是 Python 中的不同的文件模式:
模式說明
'r' 打開一個只讀文件 'w' 打開一個文件進行寫入。如果文件存在,會覆蓋它,否則會創(chuàng)建一個新文件 'a' 打開一個僅用于追加的文件。如果該文件不存在,會創(chuàng)建該文件 'x' 創(chuàng)建一個新文件。如果文件存在,則失敗 '+' 打開一個文件進行更新
我們還可以指定以文本模式“t”、默認模式或二進制模式“b”打開文件。讓我們看看如何使用簡單的語句復制圖像文件 dataquest_logo.png:
with?open('dataquest_logo.png',?'rb')?as?rf:
????with?open('data_quest_logo_copy.png',?'wb')?as?wf:
????????for?b?in?rf:
????????????wf.write(b)
上面的代碼復制 Dataquest 徽標圖像并將其存儲在同一路徑中。'rb' 模式以二進制模式打開文件并進行讀取,而 'wb' 模式以文本模式打開文件以并行寫入
讀取文本文件
在 Python 中有多種讀取文本文件的方法,下面我們介紹一些讀取文本文件內容的有用方法
到目前為止,我們已經了解到可以使用 read() 方法讀取文件的全部內容。如果我們只想從文本文件中讀取幾個字節(jié)怎么辦,可以在 read() 方法中指定字節(jié)數。讓我們嘗試一下:
with?open('zen_of_python.txt')?as?f:
????print(f.read(17))
Output:
The Zen of Python上面的簡單代碼讀取 zen_of_python.txt 文件的前 17 個字節(jié)并將它們打印出來
有時一次讀取一行文本文件的內容更有意義,在這種情況下,我們可以使用 readline() 方法
with?open('zen_of_python.txt')?as?f:
????print(f.readline())
Output:
The Zen of Python, by Tim Peters上面的代碼返回文件的第一行,如果我們再次調用該方法,它將返回文件中的第二行等,如下:
with?open('zen_of_python.txt')?as?f:
????print(f.readline())
????print(f.readline())
????print(f.readline())
????print(f.readline())
Output:
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.這種有用的方法可以幫助我們以增量方式讀取整個文件。
以下代碼通過逐行迭代來輸出整個文件,直到跟蹤我們正在讀取或寫入文件的位置的文件指針到達文件末尾。當 readline() 方法到達文件末尾時,它返回一個空字符串
with?open('zen_of_python.txt')?as?f:
????line?=?f.readline()
????while?line:
????????print(line,?end='')
????????line?=?f.readline()
Output:
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!上面的代碼在 while 循環(huán)之外讀取文件的第一行并將其分配給 line 變量。在 while 循環(huán)中,它打印存儲在 line 變量中的字符串,然后讀取文件的下一行。while 循環(huán)迭代該過程,直到 readline() 方法返回一個空字符串??兆址?while 循環(huán)中的計算結果為 False,因此迭代過程終止
讀取文本文件的另一個有用方法是 readlines() 方法,將此方法應用于文件對象會返回包含文件每一行的字符串列表
with?open('zen_of_python.txt')?as?f:
????lines?=?f.readlines()
讓我們檢查 lines 變量的數據類型,然后打印它:
print(type(lines))
print(lines)
Output:
['The Zen of Python, by Tim Peters\n', '\n', 'Beaut...]它是一個字符串列表,其中列表中的每個項目都是文本文件的一行,``\n` 轉義字符表示文件中的新行。此外,我們可以通過索引或切片操作訪問列表中的每個項目:
print(lines)
print(lines[3:5])
print(lines[-1])
Output:
['The Zen of Python, by Tim Peters\n', '\n', 'Beautiful is better than ugly.\n', ... -- let's do more of those!"]
['Explicit is better than implicit.\n', 'Simple is better than complex.\n']
Namespaces are one honking great idea -- let's do more of those!讀取 CSV 文件
到目前為止,我們已經學會了如何使用常規(guī)文本文件。但是有時數據采用 CSV 格式,數據專業(yè)人員通常會檢索所需信息并操作 CSV 文件的內容
接下來我們將使用 CSV 模塊,CSV 模塊提供了有用的方法來讀取存儲在 CSV 文件中的逗號分隔值。我們現在就嘗試一下
import?csv
with?open('chocolate.csv')?as?f:
????reader?=?csv.reader(f,?delimiter=',')
????for?row?in?reader:
????????print(row)
Output:
['Company', 'Bean Origin or Bar Name', 'REF', 'Review Date', 'Cocoa Percent', 'Company Location', 'Rating', 'Bean Type', 'Country of Origin']
['A. Morin', 'Agua Grande', '1876', '2016', '63%', 'France', '3.75', '?\xa0', 'Sao Tome']
['A. Morin', 'Kpime', '1676', '2015', '70%', 'France', '2.75', '?\xa0', 'Togo']
['A. Morin', 'Atsane', '1676', '2015', '70%', 'France', '3', '?\xa0', 'Togo']
['A. Morin', 'Akata', '1680', '2015', '70%', 'France', '3.5', '?\xa0', 'Togo']
...CSV 文件的每一行形成一個列表,其中每個項目都可以輕松的被訪問,如下所示:
import?csv
with?open('chocolate.csv')?as?f:
????reader?=?csv.reader(f,?delimiter=',')
????for?row?in?reader:
????????print("The?{}?company?is?located?in?{}.".format(row[0],?row[5]))
Output:
The Company company is located in Company Location.
The A. Morin company is located in France.
The A. Morin company is located in France.
The A. Morin company is located in France.
The A. Morin company is located in France.
The Acalli company is located in U.S.A..
The Acalli company is located in U.S.A..
The Adi company is located in Fiji.
...很多時候,使用列的名稱而不是使用它們的索引,這通常對專業(yè)人員來說更方便。在這種情況下,我們不使用 reader() 方法,而是使用返回字典對象集合的 DictReader() 方法
import?csv
with?open('chocolate.csv')?as?f:
????dict_reader?=?csv.DictReader(f,?delimiter=',')
????for?row?in?dict_reader:
????????print("The?{}?company?is?located?in?{}.".format(row['Company'],?row['Company?Location']))
Output:
The A. Morin company is located in France.
The A. Morin company is located in France.
The A. Morin company is located in France.
The A. Morin company is located in France.
The Acalli company is located in U.S.A..
The Acalli company is located in U.S.A..
The Adi company is located in Fiji.
...讀取 JSON 文件
我們主要用于存儲和交換數據的另一種流行文件格式是 JSON,JSON 代表 JavaScript Object Notation,允許我們使用逗號分隔的鍵值對存儲數據
接下來我們將加載一個 JSON 文件并將其作為 JSON 對象使用,而不是作為文本文件,為此我們需要導入 JSON 模塊。然后在 with 上下文管理器中,我們使用了屬于 json 對象的 load() 方法,它加載文件的內容并將其作為字典存儲在上下文變量中。
import?json
with?open('movie.json')?as?f:
????content?=?json.load(f)
????print(content)
Output:
{'Title': 'Bicentennial Man', 'Release Date': 'Dec 17 1999', 'MPAA Rating': 'PG', 'Running Time min': 132, 'Distributor': 'Walt Disney Pictures', 'Source': 'Based on Book/Short Story', 'Major Genre': 'Drama', 'Creative Type': 'Science Fiction', 'Director': 'Chris Columbus', 'Rotten Tomatoes Rating': 38, 'IMDB Rating': 6.4, 'IMDB Votes': 28827}讓我們檢查內容變量的數據類型:
print(type(content))
Output:
它的數據類型是字典,因此我們可以方便的從中提取數據
print('{}?directed?by?{}'.format(content['Title'],?content['Director']))
Output:
Bicentennial Man directed by Chris Columbus總結
今天我們討論了 Python 中的文件處理,重點是讀取文件的內容。我們了解了 open() 內置函數、with 上下文管理器,以及如何讀取文本、CSV 和 JSON 等常見文件類型。
好了,這就是今天分享的全部內容,喜歡就點個贊吧~


