動態

詳情 返回 返回

【Python 1-17】Python手把手教程之——文件的讀寫以及I/O操作 - 動態 詳情

作者 | 弗拉德
來源 | 弗拉德(公眾號:fulade_me)

從文件中讀取數據

文本文件可存儲的數據量很多,每當需要分析或修改存儲在文件中的信息時,讀取文件都很有用,對數據分析應用程序來説尤其 如此。例如,你可以編寫一個這樣的程序:讀取一個文本文件的內容,重新設置這些數據的格式 並將其寫入文件,讓瀏覽器能夠顯示這些內容。
要使用文本文件中的信息,首先需要將信息讀取到內存中。為此,你可以一次性讀取文件的全部內容,也可以以每次一行的方式逐步讀取。

讀取整個文件

要讀取文件,需要一個包含幾行文本的文件。下面首先來創建一個文件,它包含精確到小數點後30位的圓周率值,且在小數點後每10位處都換行:

3.1415926535 
8979323846 
2643383279

我們把它保存為pi_digits.txt文件

with open('pi_digits.txt') as file_object: 
    contents = file_object.read() 
    print(contents)

我們先來看看函數open()。要以任何方式使用文件——哪怕僅僅是打印其內容,都得先打開文件,這樣才能訪問它。函數open()接受一個參數: 要打開的文件的名稱。Python在當前執行的文件所在的目錄中查找指定的文件。在這個示例中,假如我們把文件保存為file_reader.py,因此Python在file_reader.py所在的目錄中查找pi_digits.txt。函數open()返回一個表示文件的對象。在這裏,open('pi_digits.txt')返回一個表示文件pi_digits.txt的對象,Python將這個對象存儲在我們將在後面使用的變量中。
關鍵字with在不再需要訪問文件後將其關閉。在這個程序中,注意到我們調用了open(),但沒有調用close(),你也可以調用open()close()來打開和關閉文件,但這樣做時,如果程序存在bug,導致close()語句未執行,文件將不會關閉。這看似微不足道,但未妥善地關閉文件可能會導致數據丟失或受損。如果在程序中過早地調用close(),你會發現需要使用文件時它已關閉,這會導致更多的錯誤。並非在任何情況下都能輕鬆確定關閉文件的恰當時機,但通過使用前面所示的結構,可讓Python去確定:你只管打開文件,並在需要時使用它,Python自會在合適的時候自動將其關閉。
通過打印contents的值,就可將這個文本文件的全部內容顯示出來:

3.1415926535 
8979323846 
2643383279

文件路徑

當你將類似pi_digits.txt這樣的簡單文件名傳遞給函數open()時,Python將在當前執行的文件所在的目錄中查找文件。
根據你組織文件的方式,有時可能要打開不在程序文件所屬目錄中的文件。例如,你可能將 程序文件存儲在了文件夾python_work中,而在文件夾python_work中,有一個名為text_files的文件夾,用於存儲程序文件操作的文本文件。雖然文件夾text_files包含在文件夾python_work中,但僅向open()傳遞位於該文件夾中的文件的名稱也不可行,因為Python只在文件夾python_work中查找,而不會在其子文件夾text_files中查找。要讓Python打開不與程序文件位於同一個目錄中的文件,需要提供文件路徑,它讓Python到系統的特定位置去查找。
由於文件夾text_files位於文件夾python_work中,因此可使用相對文件路徑來打開該文件夾中的文件。相對文件路徑讓Python到指定的位置去查找,而該位置是相對於當前運行的程序所在目錄的。在Linux和OS X中,你可以這樣編寫代碼:

with open('text_files/filename.txt') as file_object:

這行代碼讓Python到文件夾python_work下的文件夾text_files中去查找指定的.txt文件。在Windows系統中,在文件路徑中使用反斜槓\而不是斜槓/:

with open('text_files\filename.txt') as file_object:

你還可以將文件在計算機中的準確位置告訴Python,這樣就不用關心當前運行的程序存儲在什麼地方了。這稱為絕對文件路徑。在相對路徑行不通時,可使用絕對路徑。例如,如果text_files並不在文件夾python_work中,而在文件夾other_files中,則向open()傳遞路徑'text_files/ filename.txt'行不通,因為Python只在文件夾python_work中查找該位置。為明確地指出你希望Python到哪裏去查找,你需要提供完整的路徑。
絕對路徑通常比相對路徑更長,因此將其存儲在一個變量中,再將該變量傳遞給open()會有所幫助。在Linux和OS X中,絕對路徑類似於下面這樣:

file_path = '/home/ehmatthes/other_files/text_files/filename.txt'
with open(file_path) as file_object:

而在Windows系統中,它們類似於下面這樣:

file_path = 'C:\Users\ehmatthes\other_files\text_files\filename.txt'
with open(file_path) as file_object:

通過使用絕對路徑,可讀取系統任何地方的文件。就目前而言,最簡單的做法是,要麼將 據文件存儲在程序文件所在的目錄,要麼將其存儲在程序文件所在目錄下的一個文件夾(如text_files)中。

逐行讀取

讀取文件時,常常需要檢查其中的每一行:你可能要在文件中查找特定的信息,或者要以某種方式修改文件中的文本。例如,你可能要遍歷一個包含天氣數據的文件,並使用天氣描述中包含字樣sunny的行。在新聞報道中,你可能會查找包含標籤<headline>的行,並按特定的格式設置它。
要以每次一行的方式檢查文件,可對文件對象使用for循環:

filename = 'pi_digits.txt'
with open(filename) as file_object: 
    for line in file_object:
    print(line)

我們將要讀取的文件的名稱存儲在變量filename中,這是使用文件時一種常見的做法。由於變量filename表示的並非實際文件——它只是一個讓Python知道到哪裏去查找文件的字符串,因此可輕鬆地將'pi_digits.txt'替換為你要使用的另一個文件的名稱。

調用open()後,將一個表示文件及其內容的對象存儲到了變量file_object中。這裏也使用了關鍵字with,讓Python負責妥善地打開和關閉文件。為查看文件的內容,我們通過對文件對象執行循環來遍歷文件中的每一行,我們打印每一行時,發現空白行更多了:

3.1415926535 

8979323846

2643383279

為何會出現這些空白行呢?因為在這個文件中,每行的末尾都有一個看不見的換行符,而print語句也會加上一個換行符,因此每行末尾都有兩個換行符:一個來自文件,另一個來自print語句。

創建一個包含文件各行內容的列表

使用關鍵字with時,open()返回的文件對象只在with代碼塊內可用。如果要在with代碼塊外訪問文件的內容,可在with代碼塊內將文件的各行存儲在一個列表中,並在with代碼塊外使用該列表:你可以立即處理文件的各個部分,也可推遲到程序後面再處理。
下面的示例在with代碼塊中將文件pi_digits.txt的各行存儲在一個列表中,再在with代碼塊外打印它們:

filename = 'pi_digits.txt'
with open(filename) as file_object:
    lines = file_object.readlines() 
for line in lines:
    print(line.rstrip())

我們先使用方法readlines()從文件中讀取每一行,並將其存儲在一個列表中接下來,該列表被存儲到變量lines中;在with代碼塊外,我們依然可以使用這個變量。我們使用一個簡單的for循環來打印lines中的各行。由於列表lines的每個元素都對應於文件中的一行,因此輸出 與文件內容完全一致。

使用文件的內容

將文件讀取到內存中後,就可以以任何方式使用這些數據了。下面以簡單的方式使用圓周率 的值。首先,我們將創建一個字符串,它包含文件中存儲的所有數字,且沒有任何空格:


filename = 'pi_digits.txt'
with open(filename) as file_object: 
    lines = file_object.readlines()
pi_string = '' 
for line in lines:
    pi_string += line.rstrip()
print(pi_string) 
print(len(pi_string))

就像前一個示例一樣,我們首先打開文件,並將其中的所有行都存儲在一個列表中。我們創建了一個變量——pi_string,用於存儲圓周率的值。接下來,我們使用一個循環將各行都加入pi_string,並刪除每行末尾的換行符。接着,我們打印這個字符串及其長度:

3.1415926535 8979323846 2643383279
36

在變量pi_string存儲的字符串中,包含原來位於每行左邊的空格,為刪除這些空格,可使用strip()而不是rstrip():

filename = 'pi_30_digits.txt'
with open(filename) as file_object: 
    lines = file_object.readlines()
pi_string = ''
for line in lines:
    pi_string += line.strip()
print(pi_string) 
print(len(pi_string))

這樣,我們就獲得了一個這樣的字符串:它包含精確到30位小數的圓周率值。這個字符串長32字符,因為它還包含整數部分的3和小數點:

3.141592653589793238462643383279
36

寫入文件

保存數據的最簡單的方式之一是將其寫入到文件中。通過將輸出寫入文件,即便關閉包含程 序輸出的終端窗口,這些輸出也依然存在:你可以在程序結束運行後查看這些輸出,可與別人分享輸出文件,還可編寫程序來將這些輸出讀取到內存中並進行處理。

寫入空文件

要將文本寫入文件,你在調用open()時需要提供另一個實參,告訴Python你要寫入打開的文 件。為明白其中的工作原理,我們來將一條簡單的消息存儲到文件中,而不是將其打印到屏幕上:

filename = 'programming.txt'
with open(filename, 'w') as file_object:
    file_object.write("I love programming.")

在這個示例中,調用open()時提供了兩個實參。第一個實參也是要打開的文件的名稱; 第二個實參w告訴Python,我們要以寫入模式打開這個文件。打開文件時,可指定讀取模式r、寫入模式w、附加模式a或讓你能夠讀取和寫入文件的模式r+。如果 你省略了模式實參,Python將以默認的只讀模式打開文件。

如果你要寫入的文件不存在,函數open()將自動創建它。然而,以寫入w模式打開文件時千萬要小心,因為如果指定的文件已經存在,Python將在返回文件對象前清空該文件。
我們使用文件對象的方法write()將一個字符串寫入文件。這個程序沒有終端輸出,但如果你打開文件programming.txt,將看到其中包含如下一行內容:

I love programming.

相比於你的計算機中的其他文件,這個文件沒有什麼不同。你可以打開它、在其中輸入新文本、複製其內容、將內容粘貼到其中等。

寫入多行

函數write()不會在你寫入的文本末尾添加換行符,因此如果你寫入多行時沒有指定換行符,
文件看起來可能不是你希望的那樣:

filename = 'programming.txt'
with open(filename, 'w') as file_object:
    file_object.write("I love programming.") 
    file_object.write("I love creating new games.")

如果你打開programming.txt,將發現兩行內容擠在一起:

I love programming.I love creating new games.

要讓每個字符串都單獨佔一行,需要在write()語句中包含換行符:

filename = 'programming.txt'
with open(filename, 'w') as file_object:
    file_object.write("I love programming.\n") 
    file_object.write("I love creating new games\n")

現在,輸出出現在不同行中:

I love programming.
I love creating new games.

追加寫入文件

如果你要給文件添加內容,而不是覆蓋原有的內容,可以附加模式打開文件。你以附加模式打開文件時,Python不會在返回文件對象前清空文件,而你寫入到文件的行都將添加到文件末尾。如果指定的文件不存在,Python將為你創建一個空文件。

filename = 'programming.txt'
with open(filename, 'a') as file_object:
    file_object.write("I also love finding meaning in large datasets.\n")
    file_object.write("I love creating apps that can run in a browser.\n")

我們打開文件時指定了實參a,以便將內容附加到文件末尾,而不是覆蓋文件原來的內容。然後,我們又寫入了兩行,它們被添加到文件programming.txt末尾:

I love programming.
I love creating new games.
I also love finding meaning in large datasets.
I love creating apps that can run in a browser.

最終的結果是,文件原來的內容還在,它們後面是我們剛添加的內容。 19

小作業
17-1 在文本編輯器中新建一個文件,寫幾句話來總結一下你至
此學到的Python知識。將這個文件命名為 learning_python.txt,並將其存儲到為完成本章練習而編寫的程序所在的目錄中。編寫一個程序,讀取整個文件,並打印。
17-2 訪客:編寫一個程序,提示用户輸入其名字;用户作出響應後,將其名字寫入到文件 guest.txt中。

想查看作業答案可以去我的Githu倉庫在文件夾17-1_17-2


公眾號

user avatar u_17400586 頭像 monkeynik 頭像 sue0604 頭像 u_16281588 頭像 oeasy 頭像 u_15505879 頭像 HarmonyOS5 頭像 hejing-michael 頭像 xiaofeixiang_63ec941cad48a 頭像 aipaobudeshoutao 頭像 wnhyang 頭像 immerse 頭像
點贊 43 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.