溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python文件處理方法實例代碼分析

發(fā)布時間:2022-10-11 11:36:31 來源:億速云 閱讀:250 作者:iii 欄目:web開發(fā)

今天小編給大家分享一下Python文件處理方法實例代碼分析的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

打開文件

讓我們從最基本的文件讀取示例開始。假設我在與我的代碼文件相同的目錄中有一個文件,名為journal1.txt.

打開文件的標準方式是使用內置open()函數(shù),默認從io模塊導入。

file = open("journal1.txt", 'r')
for line in file:
    print(line)
file.close()

open()函數(shù)接受許多參數(shù),用于以高級方式與文件交互,但大多數(shù)情況下,你只需要前兩個參數(shù)

第一個參數(shù)file接受一個字符串,該字符串包含打開的文件的絕對路徑或相對路徑。這是唯一嚴格要求的參數(shù)。

第二個參數(shù)mode接受一個指示文件模式的字符串。如果未指定,將使用'rt',這意味著它將文件作為文本讀取。模式'r'實際上是相同的,因為文本模式 ( t) 是默認行為的一部分。

我可以用這行來代替,得到同樣的行為。。。

file = open("journal1.txt")

但我個人更喜歡明確指出我是在閱讀(r),寫作(w),還是你有什么。

open()返回的所有“文件”對象都是可迭代的。對于文本文件,返回一個TextIOWrapper對象。在上面的示例中,我遍歷TextIOWrapper對象文件中的行,并打印出每一行。

處理完文件后,我需要使用file.close()關閉它。 重要的是不要依賴垃圾收集器為你關閉文件,因為這種行為既不能保證也不方便實現(xiàn)。此外,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()可能是一件非常痛苦的事情,尤其是當你考慮到打開文件時可能出現(xiàn)的錯誤時。值得慶幸的是,還有一種更簡潔的方法:上下文管理器!

上下文管理器由Python 中的with語句定義。我可以使用以下語法重寫我之前的代碼:

with open("journal1.txt", 'r') as file:
    for line in file:
        print(line)

調用open()函數(shù),如果成功,則生成的TextIOWrapper對象存儲在 中file,并且可以在with語句的主體中使用。一旦控制離開with語句,file.close()就會被隱式調用;你永遠不必記得調用它!

我們將在下一章更深入地介紹這一點。

文件模式

該文檔提到了幾種可用于open()的模式:

  • r打開文件進行讀取(默認)。

  • w打開或創(chuàng)建文件以首先寫入、刪除(截斷)其內容。

  • a打開或創(chuàng)建要寫入的文件,但追加到末尾而不是截斷。

  • x創(chuàng)建并打開一個新文件進行寫入;它無法打開現(xiàn)有文件。

  • +打開文件進行讀寫(見下表)。

  • t以文本模式處理文件(默認)。

  • b以二進制模式處理文件。

這些模式標志可以組合在一起。例如,在二進制模式下,a+b允許寫入和讀取,其中寫入附加到文件末尾。

+標志始終與另一標志組合。當與r結合使用時,它添加了a的功能,但它從文件開頭開始(不截斷)。當與w、ax組合時,它也允許讀取。

使用此表可以最好地理解不同標志的行為:

| 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()函數(shù)以文本模式讀取文件,也可以直接迭代

當然,這需要使用適當?shù)奈募J綐酥敬蜷_文件進行讀?。ㄕ垍㈤啞拔募J健辈糠郑?。如果需要檢查對象文件是否可以讀取,請使用file.readable()函數(shù)。

讓我們對比一下讀取文件的三種方式:

read()

read()函數(shù)將文件的全部內容作為一個長字符串讀取。

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()從文件流中讀取的最大字符數(shù):

with open("journal1.txt", 'r') as file:
    contents = file.read(20)
    print(contents)

# Could this be where

readline()

readline()函數(shù)的行為與read()完全相同,只是它在遇到換行符時停止讀取。換行符包含在返回的字符串中。

with open("journal1.txt", 'r') as file:
    contents = file.readline()
    print(contents)

# Could this be where all missing things are found?

read()一樣,你可以指定要讀取的最大字符數(shù):

with open("journal1.txt", 'r') as file:
    contents = file.readline(20)
    print(contents)

# Could this be where

readlines()

readlines()函數(shù)以字符串列表的形式返回整個文件,每個字符串為一行。

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()函數(shù)來刪除它。

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!

你還可以通過指定最大字符數(shù)來限制從文件中讀取的內容。然而,與以前不同的是,這不是硬性限制。相反,一旦到目前為止從所有行讀取的字符總數(shù)超過了指定的限制,則只會讀取當前行的其余部分。

通過比較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

在第二個示例中,讀取前兩行的全部內容,但不再讀取。

與其他兩個函數(shù)不同,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)

兩者的區(qū)別在于第一種方法,直接迭代,是惰性的,而第二種方法在迭代內容之前首先讀取整個文件。

使用write()orwritelines()函數(shù),我們可以以幾乎相同的方式寫入文件。

這需要打開文件進行寫入(參見“文件模式”部分)。file.writable()函數(shù)可用于檢查file對象是否可寫。

在本節(jié)的示例中,我將在底部的注釋中顯示文件內容。

write()

write()函數(shù)將給定的行寫入文件。

我可以使用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存在,它將使用給定的內容創(chuàng)建。

我可以使用w文件模式覆蓋journal3.txt的全部內容:

with open("journal3.txt", 'w') as file:
    file.write("GNOMES\nWEAKNESS?\n")

# GNOMES
# WEAKNESS?
#

VpSo8f">注意:注意你的文件模式!w并將w+刪除文件的全部內容。使用aa+寫入文件末尾。

我可以使用a文件模式附加到文件中:

with open("journal3.txt", 'a') as file:
    file.write("leaf blowers\n")

# GNOMES
# WEAKNESS?
# leaf blowers
#

write()函數(shù)返回一個整數(shù),表示寫入的字符數(shù)。

writelines()

writelines()函數(shù)將字符串列表寫入文件。

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()函數(shù)只返回None。

搜索

file.seek()函數(shù)允許你在文件對象file中逐個字符地來回移動。處理文本流時,它接受一個參數(shù):一個正整數(shù),表示要移動到的新位置,表示為從開頭開始的字符數(shù)。

除了改變位置之外,該file.seek()函數(shù)還將返回一個表示文件中新絕對位置的整數(shù)。你可用file.tell()來獲取該文件的當前位置。

r+文件模式最好與函數(shù)seek()一起使用,盡管它可以與 aa+之外的任何其他文件模式一起使用。

我將首先使用seek()函數(shù)來讀取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()命令將始終覆蓋文件的現(xiàn)有內容,除非你追加到末尾。要將文本非破壞性地插入文件,通常最好將整個內容作為字符串(或列表)讀取,編輯字符串,然后將其寫回。

在這里,我將用“NONSENSE!”替換“EYEBALLS”這個詞:

with open("journal3.txt", 'r+') as file:
    file.seek(9)
    file.write("NONSENSE!")

# FLOATING NONSENSE!

打開文件后,我從頭移動到第 9 個字符,然后write()是新數(shù)據(jù)。

用二進制搜索

當你以二進制模式 ( b) 打開文件時,你可以以更動態(tài)的方式在文件中移動,使用兩個參數(shù)而不是一個參數(shù):

  • offset:字符移動的距離(可以是負數(shù))

  • whence: 計算偏移量的位置:0表示文件的開始位置(默認),1表示當前位置,2表示文件的結束位置。

不幸的是,使用whence參數(shù)不適用于以文本模式打開的文件。

文件錯誤

與處理文件相關的四個最常見錯誤如下:

FileNotFoundError

rr+模式要求文件在打開之前存在。否則,將引發(fā)FileNotFoundError錯誤:

try:
    with open("notreal.txt", 'r') as file:
        print(file.read())
except FileNotFoundError as e:
    print(e)

FileExistsError

xx+文件模式專門用于創(chuàng)建新文件。如果文件已存在,將引發(fā)FileExistsError錯誤:

try:
    with open("journal3.txt", 'x+') as file:
        print(file.read())
except FileExistsError as e:
    print(e)

UnsupportedOperation

每當你嘗試讀取僅打開用于寫入的文件或寫入僅打開用于讀取的文件時都會引發(fā)錯誤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 在幕后為我們抽象了這一點。無論操作系統(tǒng)如何,在以文本模式寫入文件時始終用作行分隔符!\n

文件路徑

到目前為止,我只使用了與代碼相同文件夾中的文件,但這很少是我們想要的!我們需要能夠構建文件路徑。

問題是,所有系統(tǒng)上的文件路徑都不相同。UNIX風格的系統(tǒng),如macOS和Linux,使用UNIX文件路徑約定,而Windows使用完全不同的方案。我們的解決方案必須對兩者都有效,這意味著硬路徑不是一個選項。

為了解決這個問題,Python 提供了兩個模塊:ospathlib

創(chuàng)建路徑

Python實際上提供了多個用于構建路徑的類,這取決于你的特定需求。但是,在大多數(shù)情況下,你應該只使用pathlib.Path

假設我想在當前用戶的主文件夾中創(chuàng)建一個名為.dead_simple_python的特殊目錄,然后將文件寫入該位置。我會這樣做:

首先,我創(chuàng)建一個Path()對象,指向最終所需的目錄(而不是文件)。

Path()構造函數(shù)中,我將路徑的每個部分作為單獨的字符串傳遞。我可以使用類方法Path.home()來獲取用戶目錄的路徑。

from pathlib import Path
import os

file_path = Path(Path.home(), ".dead_simple_python")

接下來,我將使用file_path.exists()檢查路徑是否已經(jīng)存在。如果它不存在,我將使用os.makedirs函數(shù)用于創(chuàng)建路徑中缺少的任何目錄:

if not file_path.exists():
    os.makedirs(file_path)

最后,我可以將文件名添加到已經(jīng)擁有的路徑對象中,然后打開該文件進行寫入:

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')。從技術上講,兩者的作用完全相同,盡管成員函數(shù)是首選。

相對路徑

open("journal1.txt")之所以有效,是因為它是一個相對路徑,從執(zhí)行代碼的目錄開始。

如果我的代碼所在的目錄中有一個journals/目錄,我可以使用它:

from pathlib import Path

file_path = Path("journals", "journal1.txt")

with file_path.open('r') as file:
    print(file.read())

只要我不是從絕對路徑開始,比如由Path.home()生成的路徑,路徑都是相對的。

但是如果我想向上移動一個目錄而不是向下移動呢?你可能會嘗試使用..,但正如你可能猜到的,這并不能保證在所有操作系統(tǒng)上都是可移動的。相反,我可以使用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文件處理方法實例代碼分析”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI