您好,登錄后才能下訂單哦!
今天小編給大家分享一下Python文件處理方法實例代碼分析的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
讓我們從最基本的文件讀取示例開始。假設我在與我的代碼文件相同的目錄中有一個文件,名為journal1.txt
.
打開文件的標準方式是使用內置open()
函數,默認從io
模塊導入。
file = open("journal1.txt", 'r') for line in file: print(line) file.close()
open()
函數接受許多參數,用于以高級方式與文件交互,但大多數情況下,你只需要前兩個參數
第一個參數file
接受一個字符串,該字符串包含打開的文件的絕對路徑或相對路徑。這是唯一嚴格要求的參數。
第二個參數mode
接受一個指示文件模式的字符串。如果未指定,將使用'rt'
,這意味著它將文件作為文本讀取。模式'r'
實際上是相同的,因為文本模式 ( t
) 是默認行為的一部分。
我可以用這行來代替,得到同樣的行為。。。
file = open("journal1.txt")
但我個人更喜歡明確指出我是在閱讀(r
),寫作(w
),還是你有什么。
從open()
返回的所有“文件”對象都是可迭代的。對于文本文件,返回一個TextIOWrapper
對象。在上面的示例中,我遍歷TextIOWrapper
對象文件中的行,并打印出每一行。
處理完文件后,我需要使用file.close()
關閉它。 重要的是不要依賴垃圾收集器為你關閉文件,因為這種行為既不能保證也不方便實現。此外,Python 不能保證在調用.close()
之前完成對文件的寫入。
運行該代碼,至少在我的情況下,不會打印出journal1.txt
內容:
Could this be where all missing things are found? Magic Hair Only for the Pure of Heart Not naturally occurring? Could result in minor gravity anomalies!
在實踐中,始終記住調用close()
可能是一件非常痛苦的事情,尤其是當你考慮到打開文件時可能出現的錯誤時。值得慶幸的是,還有一種更簡潔的方法:上下文管理器!
上下文管理器由Python 中的with
語句定義。我可以使用以下語法重寫我之前的代碼:
with open("journal1.txt", 'r') as file: for line in file: print(line)
調用open()
函數,如果成功,則生成的TextIOWrapper
對象存儲在 中file
,并且可以在with
語句的主體中使用。一旦控制離開with
語句,file.close()
就會被隱式調用;你永遠不必記得調用它!
我們將在下一章更深入地介紹這一點。
該文檔提到了幾種可用于open()
的模式:
r
打開文件進行讀取(默認)。
w
打開或創建文件以首先寫入、刪除(截斷)其內容。
a
打開或創建要寫入的文件,但追加到末尾而不是截斷。
x
創建并打開一個新文件進行寫入;它無法打開現有文件。
+
打開文件進行讀寫(見下表)。
t
以文本模式處理文件(默認)。
b
以二進制模式處理文件。
這些模式標志可以組合在一起。例如,在二進制模式下,a+b允許寫入和讀取,其中寫入附加到文件末尾。
+標志始終與另一標志組合。當與r
結合使用時,它添加了a
的功能,但它從文件開頭開始(不截斷)。當與w
、a
或x
組合時,它也允許讀取。
使用此表可以最好地理解不同標志的行為:
| r r+ w w+ a a+ x x+ ---------------------|---------------------------------- allow read | ? ? ? ? ? allow write | ? ? ? ? ? ? ? create new file | ? ? ? ? ? ? open existing file | ? ? ? ? ? ? erase file contents | ? ? allow seek | ? ? ? ? ? position at start | ? ? ? ? ? ? position at end | ? ?
我們可以使用read()
,readline()
或者readlines()
函數以文本模式讀取文件,也可以直接迭代
當然,這需要使用適當的文件模式標志打開文件進行讀取(請參閱“文件模式”部分)。如果需要檢查對象文件是否可以讀取,請使用file.readable()
函數。
讓我們對比一下讀取文件的三種方式:
read()
函數將文件的全部內容作為一個長字符串讀取。
with open("journal1.txt", 'r') as file: contents = file.read() print(contents) # Could this be where all missing things are found? # Magic Hair Only for the Pure of Heart # Not naturally occurring? # Could result in minor gravity anomalies!
或者,你可以告訴read()
從文件流中讀取的最大字符數:
with open("journal1.txt", 'r') as file: contents = file.read(20) print(contents) # Could this be where
readline()
函數的行為與read()
完全相同,只是它在遇到換行符時停止讀取。換行符包含在返回的字符串中。
with open("journal1.txt", 'r') as file: contents = file.readline() print(contents) # Could this be where all missing things are found?
與read()
一樣,你可以指定要讀取的最大字符數:
with open("journal1.txt", 'r') as file: contents = file.readline(20) print(contents) # Could this be where
readlines()
函數以字符串列表的形式返回整個文件,每個字符串為一行。
with open("journal1.txt", 'r') as file: contents = file.readlines() for c in contents: print(c) # Could this be where all missing things are found? # # Magic Hair Only for the Pure of Heart # # Not naturally occurring? # # Could result in minor gravity anomalies! #
你會注意到每一行都包含換行符。我們可以通過在每個字符串上調用.strip()
函數來刪除它。
with open("journal1.txt", 'r') as file: contents = file.readlines() for c in contents: print(c.strip()) # Could this be where all missing things are found? # Magic Hair Only for the Pure of Heart # Not naturally occurring? # Could result in minor gravity anomalies!
你還可以通過指定最大字符數來限制從文件中讀取的內容。然而,與以前不同的是,這不是硬性限制。相反,一旦到目前為止從所有行讀取的字符總數超過了指定的限制,則只會讀取當前行的其余部分。
通過比較read()
和readlines()
可以最好地理解這一點。首先,我將閱讀限制為60個字符:
with open("journal1.txt", 'r') as file: contents = file.read(60) print(contents) # Could this be where all missing things are found? # Magic Hair
將readlines()
與使用 60 個字符的“提示”進行比較:
with open("journal1.txt", 'r') as file: contents = file.readlines(60) for c in contents: print(c.strip()) # Could this be where all missing things are found? # Magic Hair Only for the Pure of Heart
在第二個示例中,讀取前兩行的全部內容,但不再讀取。
與其他兩個函數不同,readlines()
總是讀取整行。
如你之前所見,我們可以直接迭代文件:
with open("journal1.txt", 'r') as file: for line in file: print(line) # Could this be where all missing things are found? # Magic Hair Only for the Pure of Heart # Not naturally occurring? # Could result in minor gravity anomalies!
這在功能上與以下內容相同:
with open("journal1.txt", 'r') as file: for line in file.readlines(): print(line)
兩者的區別在于第一種方法,直接迭代,是惰性的,而第二種方法在迭代內容之前首先讀取整個文件。
使用write()
orwritelines()
函數,我們可以以幾乎相同的方式寫入文件。
這需要打開文件進行寫入(參見“文件模式”部分)。file.writable()
函數可用于檢查file
對象是否可寫。
在本節的示例中,我將在底部的注釋中顯示文件內容。
write()
函數將給定的行寫入文件。
我可以使用write()
將整個多行字符串寫入一個名為journal3.txt
的新文件,如下所示:
entry = """If you go on enough road trips chances are, you've seen a certain bumper sticker: WHAT IS THE MYSTERY SHACK? """ with open("journal3.txt", 'x') as file: file.write(entry) # If you go on enough road trips # chances are, you've seen a # certain bumper sticker: # WHAT IS THE MYSTERY SHACK? #
只要journal3.txt
不存在,它將使用給定的內容創建。
我可以使用w
文件模式覆蓋journal3.txt
的全部內容:
with open("journal3.txt", 'w') as file: file.write("GNOMES\nWEAKNESS?\n") # GNOMES # WEAKNESS? #
VpSo8f">注意:注意你的文件模式!
w
并將w+
刪除文件的全部內容。使用a
或a+
寫入文件末尾。
我可以使用a
文件模式附加到文件中:
with open("journal3.txt", 'a') as file: file.write("leaf blowers\n") # GNOMES # WEAKNESS? # leaf blowers #
write()
函數返回一個整數,表示寫入的字符數。
writelines()
函數將字符串列表寫入文件。
lines = [ "Finally back safe and sound\n", "from one of the weirdest days\n", "at Gravity Falls.\n" ] with open("journal3.txt", 'w') as file: file.writelines(lines) # Finally back safe and sound # from one of the weirdest days # at Gravity Falls. #
與 withwrite()
不同,writelines()
函數只返回None
。
file.seek()
函數允許你在文件對象file
中逐個字符地來回移動。處理文本流時,它接受一個參數:一個正整數,表示要移動到的新位置,表示為從開頭開始的字符數。
除了改變位置之外,該file.seek()
函數還將返回一個表示文件中新絕對位置的整數。你可用file.tell()
來獲取該文件的當前位置。
r+
文件模式最好與函數seek()
一起使用,盡管它可以與除 a
和a+
之外的任何其他文件模式一起使用。
我將首先使用seek()
函數來讀取journal1.txt
文件的一部分:
with open("journal1.txt", 'r') as file: file.seek(50) contents = file.read(5) print(contents) # MAGIC
我將編寫journal3.txt
文件的新初始版本:
with open("journal3.txt", 'w') as file: file.write("FLOATING EYEBALLS") # FLOATING EYEBALLS
我可以使用該r+
模式更改此文件的一部分。
注意:
write()
命令將始終覆蓋文件的現有內容,除非你追加到末尾。要將文本非破壞性地插入文件,通常最好將整個內容作為字符串(或列表)讀取,編輯字符串,然后將其寫回。
在這里,我將用“NONSENSE!”替換“EYEBALLS”這個詞:
with open("journal3.txt", 'r+') as file: file.seek(9) file.write("NONSENSE!") # FLOATING NONSENSE!
打開文件后,我從頭移動到第 9 個字符,然后write()
是新數據。
當你以二進制模式 ( b
) 打開文件時,你可以以更動態的方式在文件中移動,使用兩個參數而不是一個參數:
offset
:字符移動的距離(可以是負數)
whence
: 計算偏移量的位置:0
表示文件的開始位置(默認),1
表示當前位置,2
表示文件的結束位置。
不幸的是,使用whence
參數不適用于以文本模式打開的文件。
與處理文件相關的四個最常見錯誤如下:
r
和r+
模式要求文件在打開之前存在。否則,將引發FileNotFoundError
錯誤:
try: with open("notreal.txt", 'r') as file: print(file.read()) except FileNotFoundError as e: print(e)
x
和x+
文件模式專門用于創建新文件。如果文件已存在,將引發FileExistsError
錯誤:
try: with open("journal3.txt", 'x+') as file: print(file.read()) except FileExistsError as e: print(e)
每當你嘗試讀取僅打開用于寫入的文件或寫入僅打開用于讀取的文件時都會引發錯誤io.UnsupportedOperation
:
import io try: with open("journal3.txt", 'w') as file: print(file.read()) except io.UnsupportedOperation as e: print(e) try: with open("journal3.txt", 'r') as file: file.write('') except io.UnsupportedOperation as e: print(e)
一些聰明的讀者會記得,雖然UNIX使用\n
作為行分隔符,但Windows使用\r\n
。當我們讀寫文件時,這肯定很重要,對吧?
事實上,Python 在幕后為我們抽象了這一點。無論操作系統如何,在以文本模式寫入文件時始終用作行分隔符!\n
到目前為止,我只使用了與代碼相同文件夾中的文件,但這很少是我們想要的!我們需要能夠構建文件路徑。
問題是,所有系統上的文件路徑都不相同。UNIX風格的系統,如macOS和Linux,使用UNIX文件路徑約定,而Windows使用完全不同的方案。我們的解決方案必須對兩者都有效,這意味著硬路徑不是一個選項。
為了解決這個問題,Python 提供了兩個模塊:os
和pathlib
。
Python實際上提供了多個用于構建路徑的類,這取決于你的特定需求。但是,在大多數情況下,你應該只使用pathlib.Path
。
假設我想在當前用戶的主文件夾中創建一個名為.dead_simple_python
的特殊目錄,然后將文件寫入該位置。我會這樣做:
首先,我創建一個Path()
對象,指向最終所需的目錄(而不是文件)。
在Path()
構造函數中,我將路徑的每個部分作為單獨的字符串傳遞。我可以使用類方法Path.home()
來獲取用戶目錄的路徑。
from pathlib import Path import os file_path = Path(Path.home(), ".dead_simple_python")
接下來,我將使用file_path.exists()
檢查路徑是否已經存在。如果它不存在,我將使用os.makedirs
函數用于創建路徑中缺少的任何目錄:
if not file_path.exists(): os.makedirs(file_path)
最后,我可以將文件名添加到已經擁有的路徑對象中,然后打開該文件進行寫入:
file_path = file_path.joinpath("journal4.txt") with file_path.open('w') as file: lines = [ "If you've ever taken a road trip \n", "through the Pacific Northwest, you've \n", "probably seen a bumper sticker for a \n", "place called Gravity Falls.\n" ] file.writelines(lines)
你會注意到我使用了file_path.open('w')
,而不是open(file_path, 'w')
。從技術上講,兩者的作用完全相同,盡管成員函數是首選。
open("journal1.txt")
之所以有效,是因為它是一個相對路徑,從執行代碼的目錄開始。
如果我的代碼所在的目錄中有一個journals/
目錄,我可以使用它:
from pathlib import Path file_path = Path("journals", "journal1.txt") with file_path.open('r') as file: print(file.read())
只要我不是從絕對路徑開始,比如由Path.home()
生成的路徑,路徑都是相對的。
但是如果我想向上移動一個目錄而不是向下移動呢?你可能會嘗試使用..
,但正如你可能猜到的,這并不能保證在所有操作系統上都是可移動的。相反,我可以使用os.pardir
移動到上一個目錄。
想象一下,我們有一個如下所示的目錄結構:
example ├── code │ └── read_file.py └── journals └── journal1.txt
如果在path_relative2/code
運行python read_file.py
,我可以通過以下方式訪問journal1.txt
:
from pathlib import Path import os file_path = Path(os.pardir, "journals", "journal1.txt") with file_path.open('r') as file: print(file.read())
以上就是“Python文件處理方法實例代碼分析”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。