【Python】第七章 I/O

2020-08-09 09:15:52

該文章內容整理自《Python程式設計:從入門到實踐》、《流暢的Python》、以及網上各大部落格

I/O

基本輸入輸出

input()

Python2中有 input() 和 raw_input() 兩個內建的函數可從標準輸入讀取數據,它預設來自鍵盤。但在Python3中,raw_input()函數已被棄用

  • input():以字串形式讀入數據,若要讀入其他形式則需要另行轉換
x = int(input("請輸入x="))
y = int(input("請輸入y="))
z = x + y
print("x + y = ", z)
  • raw_input():從標準輸入中以字串形式讀取一個行,並去掉結尾的換行符

print()

print 在 Python3 中是一個函數,但在 Python2 中只是一個關鍵字。print()的一般形式爲
print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False)
其中

  • objects:輸出列表,一次輸出多個用逗號分隔的不同類型的物件
  • sep:分隔字元,表示輸出多個物件時用來間隔物件的字元。預設值是一個空格
  • end:結束字元,表示輸出完物件後用來什麼字元結尾。預設值是換行符 \n
  • file:寫入的檔案物件
  • flush:表示流是否會被強制重新整理。預設爲 False,當爲 True 時,在輸出完物件後,遊標移動到輸出物件前的位置,下一次的輸出會覆蓋本次輸出

print()的格式化輸出可通過字串的format()函數來實現

檔案操作

Python 提供了內建的檔案物件,以及對檔案、目錄進行操作的內建模組,通過這些技術可以很方便地將數據儲存到檔案中。Python 中對檔案的操作有很多種,常見的操作包括建立、刪除、修改許可權、讀取、寫入等,這些操作可大致分爲以下 2 類:

  • 刪除、修改許可權:作用於檔案本身,屬於系統級操作。對檔案的系統級操作功能單一,比較容易實現,可以藉助 Python 中的專用模組(os、sys 等)的指定函數來實現。例如刪除檔案「a.txt」可通過呼叫 os 模組中的 remove 函數來完成,即os.remove(「a.txt」)
  • 寫入、讀取:是檔案最常用的操作,作用於檔案的內容,屬於應用級操作。檔案的應用級操作可以分爲以下 3 步,每一步都需要藉助對應的函數實現
    1. 開啓檔案:使用 open() 函數,該函數會返回一個檔案物件
    2. 對已開啓檔案做讀/寫操作:讀取檔案內容可使用 read()、readline() 以及 readlines() 函數;向檔案中寫入內容,可以使用 write() 函數
    3. 關閉檔案:完成對檔案的讀/寫操作之後,最後需要關閉檔案,可以使用 close() 函數

檔案路徑

檔案物件有檔名和路徑兩個關鍵屬性。對於路徑,在 Windows 中路徑用反斜槓「\」作分隔符;在 Linux 中則用斜槓「/」。而爲了相容這兩種情況,Python提供了 os.path.join() 函數來將多個元件合成路徑。 若各元件名首字母不包含分隔符,則函數會自動加上系統對應的分隔符;若有一個元件是一個絕對路徑,則在它之前的所有元件均會被捨棄。如

import os

p1 = os.path.join('home', 'develop', 'code')
# home/develop/code

p2 = os.path.join('home', '/develop', 'code')
# /develop/code

關於當前工作路徑、絕對路徑和相對路徑

  1. 當前工作路徑:表示執行當前程式所在目錄。Python提供了 os.getcwd() 和 os.chdir(new_path) 函數來檢視和修改當前路徑
  2. 絕對路徑:從根資料夾開始,Window 系統中以碟符(C: 、D:)作爲根資料夾,而 OS X 或者 Linux 系統中以 / 作爲根資料夾
  3. 相對路徑:相對於當前工作路徑所在的位置。在使用相對路徑表示某檔案所在的位置時,使用 .\ 表示當前所在目錄,…\ 表示當前所在目錄的父目錄

os.path 模組還提供了一些函數來處理絕對路徑和相對路徑

  • os.path.abspath(path):返回 path 參數的絕對路徑的字串,這是將相對路徑轉換爲絕對路徑的簡便方法
  • os.path.isabs(path):如果參數是一個絕對路徑,就返回 True;如果是一個相對路徑,就返回 False
  • os.path.relpath(path, start):返回從 start 路徑到 path 的相對路徑的字串。如果沒有提供 start,就使用當前工作目錄作爲開始路徑
  • os.path.dirname(path):返回一個字串,它包含 path 參數中最後一個斜槓之前的所有內容
  • os.path.basename(path):返回一個字串,它包含 path 參數中最後一個斜槓之後的所有內容
  • os.path.split(path):返回由 path 參數的目錄名稱和基本名稱組成的元組,即將路徑拆成所在目錄路徑和檔名。雖然可以直接使用(os.path.dirname(path), os.path.basename(path)),但使用os.path.split(path)更爲便捷
  • os.path.exists(path):如果 path 參數所指的檔案或資料夾存在返回 True,否則返回 False
  • os.path.isfile(path):如果 path 參數存在且爲檔案則返回 True,否則返回 False
  • os.path.isdir(path):如果 path 參數存在且爲資料夾則返回 True,否則返回 False

開啓檔案

Python 內建的 open() 方法用於開啓一個檔案,並返迴檔案物件。如果該檔案無法被開啓,會拋出 OSError。其一般形式爲
file object = open(file, mode=‘r’, buffering=-1, encoding=None)
其中

  • file:表示將要開啓的檔案的路徑(絕對路徑或者當前工作目錄的相對路徑)
  • mode:決定開啓檔案的模式爲只讀,寫入,追加等。預設只讀 r
    • t:文字模式
    • x:寫模式,新建一個檔案,如果該檔案已存在則會報錯
    • b:二進制模式
    • +:開啓一個檔案進行更新(可讀可寫)
    • U:通用換行模式(Python 3 不支援)
    • r:以只讀方式開啓檔案。檔案的指針將會放在檔案的開頭。這是預設模式
    • rb:以二進制格式開啓一個檔案用於只讀。檔案指針將會放在檔案的開頭。這是預設模式。一般用於非文字檔案如圖片等
    • r+:開啓一個檔案用於讀寫。檔案指針將會放在檔案的開頭
    • rb+:以二進制格式開啓一個檔案用於讀寫。檔案指針將會放在檔案的開頭。一般用於非文字檔案如圖片等
    • w:開啓一個檔案只用於寫入。如果該檔案已存在則開啓檔案,並從開頭開始編輯,即原有內容會被刪除。如果該檔案不存在,建立新檔案
    • wb:以二進制格式開啓一個檔案只用於寫入。如果該檔案已存在則開啓檔案,並從開頭開始編輯,即原有內容會被刪除。如果該檔案不存在,建立新檔案。一般用於非文字檔案如圖片等
    • w+:開啓一個檔案用於讀寫。如果該檔案已存在則開啓檔案,並從開頭開始編輯,即原有內容會被刪除。如果該檔案不存在,建立新檔案
    • wb+:以二進制格式開啓一個檔案用於讀寫。如果該檔案已存在則開啓檔案,並從開頭開始編輯,即原有內容會被刪除。如果該檔案不存在,建立新檔案。一般用於非文字檔案如圖片等
    • a:開啓一個檔案用於追加。如果該檔案已存在,檔案指針將會放在檔案的結尾。也就是說,新的內容將會被寫入到已有內容之後。如果該檔案不存在,建立新檔案進行寫入
    • ab:以二進制格式開啓一個檔案用於追加。如果該檔案已存在,檔案指針將會放在檔案的結尾。也就是說,新的內容將會被寫入到已有內容之後。如果該檔案不存在,建立新檔案進行寫入
    • a+:開啓一個檔案用於讀寫。如果該檔案已存在,檔案指針將會放在檔案的結尾。檔案開啓時會是追加模式。如果該檔案不存在,建立新檔案用於讀寫
    • ab+:以二進制格式開啓一個檔案用於追加。如果該檔案已存在,檔案指針將會放在檔案的結尾。如果該檔案不存在,建立新檔案用於讀寫
  • buffering:如果buffering的值被設爲0,就不會有寄存。如果buffering的值取1,存取檔案時會寄存行。如果將buffering的值設爲大於1的整數,表明瞭這就是的寄存區的緩衝大小。如果取負值,寄存區的緩衝大小則爲系統預設。如果不使用緩衝區,則程式在執行 I/O 操作時,記憶體和外設就必須進行同步讀寫操作,即記憶體必須等待外設 I/O 一個位元組之後,才能 纔能再次 I/O 一個位元組。這意味着,記憶體中的程式大部分時間都處於等待狀態
  • encoding:手動設定開啓檔案時所使用的編碼格式,不同平臺的 ecoding 參數值也不同,以 Windows 爲例,其預設爲 cp936(實際上就是 GBK 編碼)。一般使用utf8。預設採用 GBK 編碼。只在文字模式下使用,否則會拋出 ValueError 異常

一個檔案被開啓後,就有建立一個file物件,其包含的屬性有

  • file.name:返迴檔案的名稱
  • file.mode:返回被開啓檔案的存取模式
  • file.encoding:返回開啓檔案時使用的編碼格式
  • file.softspace:末尾是否強制加空格
  • file.closed:返回true如果檔案已被關閉,否則返回false
  • file.readable():判斷檔案物件是否可讀
  • file.writeable():判斷檔案物件是否可寫

關於本文檔案和二進制檔案
文字檔案通常用來儲存肉眼可見的字元,比如 .txt 檔案、.c 檔案、.dat 檔案等,用文字編輯器開啓這些檔案就能夠順利看懂檔案的內容。而二進制檔案通常用來儲存視訊、圖片、音訊等不可閱讀的內容,當用文字編輯器開啓這些檔案,會看到一堆亂碼。但實際上,從數據儲存的角度上分析,二進制檔案和文字檔案沒有區別,它們的內容都是以二進制的形式儲存在磁碟中的。之所以能看懂文字檔案的內容,是因爲文字檔案中採用的是 ASCII、UTF-8、GBK 等字元編碼,文字編輯器可以識別出這些編碼格式,並將編碼值轉換成字元展示出來。而對於二進制檔案,文字編輯器無法識別這些檔案的編碼格式,只能按照字元編碼格式胡亂解析,所以最終看到的是一堆亂碼
使用 open() 函數以文字格式開啓檔案和以二進制格式開啓檔案,唯一的區別是對檔案中換行符的處理不同。在 Windows 系統中,檔案中用 「\r\n」 作爲行末識別符號(即換行符),當以文字格式讀取檔案時,會將 「\r\n」 轉換成 「\n」;反之,以文字格式將數據寫入檔案時,會將 「\n」 轉換成 「\r\n」。這種隱式轉換換行符的行爲,對用文字格式開啓文字檔案是沒有問題的,但如果用文字格式開啓二進制檔案,就有可能改變文字中的數據(將 \r\n 隱式轉換爲 \n)。而在 Unix/Linux 系統中,預設的檔案換行符就是 \n,因此在 Unix/Linux 系統中文字格式和二進制格式並無本質的區別
總的來說,爲了保險起見,對於 Windows平臺最好用 b 開啓二進制檔案;對於 Unix/Linux 平臺,開啓二進制檔案,可以用 b,也可以不用

檔案讀寫

Python 提供了 read()、readline()、readlines()、write() 和 writelines() 函數,以實現在可讀模式下讀取檔案中數據及在可寫模式下向檔案中寫入指定內容的操作

read()

read()函數用於逐個位元組或者字元讀取檔案中的內容。如果檔案是以文字模式(非二進制模式)開啓的,則 read() 函數會逐個字元進行讀取;反之,如果檔案以二進制模式開啓,則 read() 函數會逐個位元組進行讀取,並且返回的字串以b開頭,表明爲二進制格式。其一般形式爲
file.read([size])
其中,file 表示已開啓的檔案物件;size 作爲一個可選參數,用於指定一次最多可讀取的字元(位元組)個數,此時若在檔案沒有關閉的情況下再次呼叫 read() 則會繼續在上次遊標所在處開始讀,如果省略,則預設一次性讀取所有內容,但正因爲如此,如果檔案非常大,尤其是大於記憶體時,則無法使用read()方法

在使用 read() 函數時,如果 Python 直譯器提示 UnicodeDecodeError 異常,其原因在於目標檔案使用的編碼格式和 open() 函數開啓該檔案時使用的編碼格式不匹配。除了見編碼格式調整一致之外,還有一種方法,先使用二進制模式讀取檔案,然後呼叫 bytes 的 decode() 方法,使用目標檔案的編碼格式,將讀取到的位元組串轉換成認識的字串

readline()

readline()函數用於逐行讀取檔案中的內容,包含最後的換行符「\n」。其一般形式爲
file.readline([size])
其中,file 爲開啓的檔案物件;size 爲可選參數,用於指定讀取每一行時,一次最多讀取的字元(位元組)數,此時若在檔案沒有關閉的情況下再次呼叫 readline() 則會繼續在上次遊標所在處開始讀 size 個字元或者到換行符爲止

注意,由於 readline() 函數在讀取檔案中一行的內容時,會讀取最後的換行符「\n」,再加上 print() 函數輸出內容時預設會換行,所以輸出結果中會看到多出了一個空行

readlines()

readlines()函數用於一次性讀取檔案中所有行,並返回一個列表,列表中的每一項爲檔案中的每一行。速度要比 readline() 快

write()

Python 中的檔案物件提供了 write() 函數,可以向檔案中寫入指定內容。其一般形式爲
file.write(string)

另外,在寫入檔案完成後,一定要呼叫 close() 函數將開啓的檔案關閉,否則寫入的內容不會儲存到檔案中。這是因爲在寫入檔案內容時,操作系統不會立刻把數據寫入磁碟,而是先快取起來,只有呼叫 close() 函數時,操作系統纔會保證把沒有寫入的數據全部寫入磁碟檔案中。除此之外,如果向檔案寫入數據後,不想馬上關閉檔案,也可以呼叫檔案物件內建的 flush() 函數,它可以實現將緩衝區的數據寫入檔案中

writelines()

Python還提供了 writelines() 函數來實現將字串列表寫入檔案中。因而可以直接在使用檔案a的 readlines() 函數返回值作爲檔案b的writelines() 函數的參數,將檔案a的內容全部複製到檔案b中

注意,使用 writelines() 函數向檔案中寫入多行數據時,不會自動給各行新增換行符,只會直接按照字串列表內容寫入檔案

檔案指針

檔案指針用於標明檔案讀寫的起始位置。注意,當向檔案中寫入數據時,如果不是檔案的尾部,寫入位置的原有數據不會自行向後移動,新寫入的數據會將檔案中處於該位置的數據直接覆蓋掉。爲移動檔案指針,實現檔案內容的隨機讀寫,檔案物件提供了 tell() 函數和 seek() 函數

  • tell():用於判斷檔案指針當前所處的位置。其一般形式爲file.tell()。函數返迴檔案指針位置,位置下標從0開始計算
  • seek():函數用於移動檔案指針到檔案的指定位置。其一般形式爲file.seek(offset[, whence]),其中
    • offset:表示相對於 whence 位置檔案指針的偏移量,正數表示向後偏移,負數表示向前偏移。注意,當 offset 值非 0 時,Python 要求檔案必須要以二進制格式開啓,否則會拋出 io.UnsupportedOperation 錯誤
    • whence:作爲可選參數,用於指定檔案指針要放置的位置,該參數的參數值有 3 個選擇:0 代表檔案頭(預設值)、1 代表當前位置、2 代表檔案尾

關閉檔案

close() 函數是用來關閉已開啓檔案,在用 open() 函數開啓的檔案,完成檔案讀寫操作之後,一定要呼叫 close() 函數將其關閉。除了之前說過會對寫檔案產生影響外,不使用 close() 函數直接對檔案進行系統級別的操作(如刪除檔案)會報錯。其一般形式爲
file.close()

with as

爲了更好地避免沒有使用 close() 函數關閉檔案的問題,Python 引入了 with as 語句操作上下文管理器(context manager),自動分配並且釋放資源。其一般形式爲

with expression [as target]# ...

其中,target 參數用於指定一個變數,該語句會將 expression 指定的結果儲存到該變數中

簡單的理解,同時包含 __enter__() 和 __exit__() 方法的物件就是上下文管理器。也就是說,上下文管理器必須實現如下兩個方法:

  • __enter__(self):進入上下文管理器自動呼叫的方法,該方法會在 with as 程式碼塊執行之前執行。如果 with 語句有 as子句,那麼該方法的返回值會被賦值給 as 子句後的變數;該方法可以返回多個值,因此在 as 子句後面也可以指定多個變數(多個變數必須由「()」括起來組成元組)
  • __exit__(self, exc_type, exc_value, exc_traceback):退出上下文管理器自動呼叫的方法。該方法會在 with as 程式碼塊執行之後執行。如果 with as 程式碼塊成功執行結束,程式自動呼叫該方法,呼叫該方法的三個參數都爲 None:如果 with as 程式碼塊因爲異常而中止,程式也自動呼叫該方法,使用 sys.exc_info 得到的異常資訊將作爲呼叫該方法的參數。注意,當出現異常時,如果 __exit__() 返回 False(預設不寫返回值時,即爲 False),則會重新拋出異常,讓 with as 之外的語句邏輯來處理異常;反之,如果返回 True,則忽略異常,不再對異常進行處理

當 with as 操作上下文管理器時,就會在執行語句體之前,先執行上下文管理器的 __enter__() 方法,然後再執行語句體,最後執行 __exit__() 方法

構建上下文管理器,常見的有 2 種方式:

  • 基於類實現:只要一個類實現了__enter__() 和 __exit__() 方法,程式就可以使用 with as 語句來管理它。檔案物件也實現了這兩個方法,因此可以接受 with as 語句的管理
class Open:
    def __init__(self, filepath, mode='r', encoding='utf-8'):
        self.filepath = filepath
        self.mode = mode
        self.encoding = encoding

    def __enter__(self):
        # print('enter')
        self.f = open(self.filepath, mode=self.mode, encoding=self.encoding)
        return self.f

    def __exit__(self, exc_type, exc_val, exc_tb):
        # print('exit')
        self.f.close()
        return True

    def __getattr__(self, item):
        return getattr(self.f, item)

with Open('a.txt', 'w') as f:
    print(f)
    f.write('aaaaaa')
    f.wasdf  #拋出異常,交給__exit__處理
  • 基於生成器實現: file_manager() 就是一個生成器,當我們執行 with as 語句時,便會開啓檔案,並返迴檔案物件 f;當 with 語句執行完後,finally 中的關閉檔案操作便會執行。另外可以看到,使用基於生成器的上下文管理器時,不再用定義 __enter__() 和 __exit__() 方法
from contextlib import contextmanager
@contextmanager
def file_manager(name, mode):
    try:
        f = open(name, mode)
        yield f
    finally:
        f.close()
       
with file_manager('a.txt', 'w') as f:
    f.write('hello world')

基於類的上下文管理器和基於生成器的上下文管理器,這兩者在功能上是一致的。只不過,基於類的上下文管理器更加靈活,適用於大型的系統開發,而基於生成器的上下文管理器更加方便、簡潔,適用於中小型程式。但是,無論使用哪一種,不用忘記在方法 __exit__() 或者是 finally 塊中釋放資源

常用模組

pickle模組

Python 中有個序列化過程叫作 pickle,能夠實現任意物件與文字之間的相互轉化,也可以實現任意物件與二進制之間的相互轉化。也就是說,pickle 可以實現 Python 物件的儲存及恢復

pickle 模組提供了以下函數:

  1. dumps():將 Python 中的物件序列化成二進制物件,並返回。其一般形式爲dumps(obj, protocol=None, *, fix_imports=True)。其中,obj表示要轉換的 Python 物件;protocol爲pickle 的轉碼協定,取值爲 0、1、2、3、4,其中 0、1、2 對應 Python 早期的版本,3 和 4 則對應 Python 3 版本及之後的版本。未指定情況下,預設爲 3。其它參數則是爲了相容 Python 2 版本而保留的參數,Python 3 中可以忽略
import pickle
tup1 = ('I love Python', {1,2,3}, None)
p1 = pickle.dumps(tup1)
print(p1)
  1. loads():讀取給定的二進制物件數據,並將其轉換爲 Python 物件。其一般形式爲loads(data, *, fix_imports=True, encoding=‘ASCII’, errors=‘strict’)。其中,data 參數表示要轉換的二進制物件,其它參數只是爲了相容 Python 2 版本而保留的,Python 3 中可以忽略。注意,在使用 loads() 函數將二進制物件反序列化成 Python 物件時,會自動識別轉碼協定,所以不需要將轉碼協定當作參數傳入。並且,當待轉換的二進制物件的位元組數超過 pickle 的 Python 物件時,多餘的位元組將被忽略
import pickle
tup1 = ('I love Python', {1,2,3}, None)
p1 = pickle.dumps(tup1)
t2 = pickle.loads(p1)
print(t2)
  1. dump():將 Python 中的物件序列化成二進制物件,並寫入檔案。其一般形式爲dump (obj, file,protocol=None, *, fix mports=True)。其中,obj爲要轉換的 Python 物件;file爲轉換到指定的二進制檔案中,要求該檔案必須是以"wb"的開啓方式進行操作;protocol 和 dumps() 函數中 protocol 參數的含義完全相同;其他參數爲了相容以前 Python 2 版本而保留的參數,可以忽略
import pickle
tup1 = ('I love Python', {1,2,3}, None)
with open ("a.txt", 'wb') as f:
    pickle.dump(tup1, f)
  1. load():讀取指定的序列化數據檔案,並返回物件。其一般形式爲load(file, *, fix_imports=True, encoding=‘ASCII’, errors=‘strict’)。其中,file 參數表示要轉換的二進制物件檔案(必須以 「rb」 的開啓方式操作檔案),其它參數只是爲了相容 Python 2 版本而保留的參數,可以忽略
import pickle
tup1 = ('I love Python', {1,2,3}, None)
with open ("a.txt", 'wb') as f:
    pickle.dump(tup1, f)
with open ("a.txt", 'rb') as f:
    print(pickle.load(f))

fileinput模組

Python 提供了 fileinput 模組,該模組中的 input() 函數能同時開啓指定的多個檔案,還可以逐個讀取這些檔案中的內容。其一般形式爲
fileinput.input(files=「filename1, filename2, …」, inplace=False, backup=’’, bufsize=0, mode=‘r’, openhook=None)
此函數會返回一個 FileInput 物件,可以理解爲是將多個指定檔案合併之後的檔案物件。其中

  • files:多個檔案的路徑列表
  • inplace:用於指定是否將標準輸出的結果寫回到檔案,此參數預設值爲 False
  • backup:用於指定備份檔案的擴充套件名
  • bufsize:指定緩衝區的大小,預設爲 0
  • mode:開啓檔案的格式,預設爲 r(只讀格式)
  • openhook:控制檔案的開啓方式,例如編碼格式等

注意,和 open() 函數不同,input() 函數不能指定開啓檔案的編碼格式,這意味着使用該函數讀取的所有檔案,除非以二進制方式進行讀取,否則該檔案編碼格式都必須和當前操作系統預設的編碼格式相同,不然 Python 直譯器可能會提示 UnicodeDecodeError 錯誤。同時,fileinput 物件無需呼叫類似 read()、readline()、readlines() 這樣的函數,直接通過 for 回圈即可按次序讀取多個檔案中的數據

import fileinput
for line in fileinput.input(files=('my_file.txt', 'file.txt')):
    print(line)
fileinput.close()

除此之外,fileinput 模組還提供了很多使用的函數

  • fileinput.filename():返回當前正在讀取的檔名稱
  • fileinput.fileno():返回當前正在讀取檔案的檔案描述符
  • fileinput.lineno():返回當前讀取了多少行
  • fileinput.filelineno():返回當前正在讀取的內容位於當前檔案中的行號
  • fileinput.isfirstline():判斷當前讀取的內容在當前檔案中是否位於第 1 行
  • fileinput.nextfile():關閉當前正在讀取的檔案,並開始讀取下一個檔案
  • fileinput.close():關閉 FileInput 物件

linecache模組

Python 提供了 linecache 模組,用來讀取指定檔案中的指定行。linecache 模組常用來讀取 Python 原始檔中的程式碼,它使用的是 UTF-8 編碼格式來讀取檔案內容。這意味着,使用該模組讀取的檔案,其編碼格式也必須爲 UTF-8,否則要麼讀取出來的數據是亂碼,要麼直接讀取失敗(Python 直譯器會報 SyntaxError 異常)

linecache 模組中常用的函數有:

  • linecache.getline(filename, lineno, module_globals=None):讀取指定模組中指定檔案的指定行(僅讀取指定檔案時,無需指定模組)。其中,filename 參數用來指定檔名,lineno 用來指定行號,module_globals 參數用來指定要讀取的具體模組名。當指定檔案以相對路徑的方式傳給 filename 參數時,該函數以按照 sys.path 規定的路徑查詢該檔案
  • linecache.clearcache():如果程式某處不再需要之前使用 getline() 函數讀取的數據,則可以使用該函數清空快取
  • linecache.checkcache(filename=None):檢查快取的有效性,即如果使用 getline() 函數讀取的數據,其實在本地已經被修改,而我們需要的是新的數據,此時就可以使用該函數檢查快取的是否爲新的數據。注意,如果省略檔名,該函數將檢測所有快取數據的有效性
import linecache
import string

print(linecache.getline(string.__file__, 3))
print(linecache.getline('my_file.txt', 2))

pathlib模組

pathlib 模組中包含的是一些類,它們的繼承關係如圖所示
在这里插入图片描述

pathlib 模組的操作物件是各種操作系統中使用的路徑

  • PurePath 類會將路徑看做是一個普通的字串,實現將多個指定的字串拼接成適用於當前操作系統的路徑格式,同時還可以判斷任意兩個路徑是否相等,但並不會關心該路徑是否真實有效。在使用 PurePath 類時,如果在 UNIX 或 Mac OS X 系統上使用 PurePath 建立物件,該類的構造方法實際返回的是 PurePosixPath 物件;反之,如果在 Windows 系統上使用 PurePath 建立物件,該類的構造方法返回的是 PureWindowsPath 物件。注意,通過PurePath 類構建的路徑,雖然本質上是字串型別,但與字串並不完全一致,若要使其爲字串型別還需要使用 str()
  • PurePosixPath 和 PureWindowsPath 是 PurePath 的子類,前者用於操作 UNIX(包括 Mac OS X)風格的路徑,後者用於操作 Windows 風格的路徑
  • Path 類和以上 3 個類不同,它操作的路徑一定是真實有效的。Path 類提供了判斷路徑是否真實存在的方法
  • PosixPath 和 WindowPath 是 Path 的子類,分別用於操作 Unix(Mac OS X)風格的路徑和 Windows 風格的路徑
from pathlib import *

print(PurePath('a','b','c')) # a\b\c
print(PurePath()) # .
print(PurePath('.')) # .
print(PurePath('C://','D://','my_file.txt')) # D:\my_file.txt
print(PurePath('C://./my_file.txt')) # C:\my_file.txt

# Unix風格的路徑區分大小寫
print(PurePosixPath('C://my_file.txt') == PurePosixPath('C://My_file.txt'))
# Windows風格的路徑不區分大小寫
print(PureWindowsPath('C://my_file.txt') == PureWindowsPath('C://My_file.txt'))

# 支援直接使用斜槓(/)作爲多個字串之間的連線符
path = PurePosixPath('C://')
print(path / 'my_file.txt')

PurePath類範例屬性和實體方法

  • PurePath.parts:返迴路徑字串中所包含的各部分
  • PurePath.drive:返迴路徑字串中的驅動器碟符
  • PurePath.root:返迴路徑字串中的根路徑
  • PurePath.anchor:返迴路徑字串中的碟符和根路徑
  • PurePath.parents:返回當前路徑的全部父路徑
  • PurPath.parent:返回當前路徑的上一級路徑,相當於 parents[0] 的返回值
  • PurePath.name:返回當前路徑中的檔名
  • PurePath.suffixes:返回當前路徑中的檔案所有後綴名
  • PurePath.suffix:返回當前路徑中的檔案後綴名。相當於 suffixes 屬性返回的列表的最後一個元素
  • PurePath.stem:返回當前路徑中的主檔名
  • PurePath.as_posix():將當前路徑轉換成 UNIX 風格的路徑
  • PurePath.as_uri():將當前路徑轉換成 URL。只有絕對路徑才能 纔能轉換,否則將會引發 ValueError
  • PurePath.is_absolute():判斷當前路徑是否爲絕對路徑
  • PurePath.joinpath(*other):將多個路徑連線在一起,作用類似於前面介紹的斜槓(/)連線符。
  • PurePath.match(pattern):判斷當前路徑是否匹配指定萬用字元
  • PurePath.relative_to(*other):獲取當前路徑中去除基準路徑之後的結果
  • PurePath.with_name(name):將當前路徑中的檔名替換成新檔名。如果當前路徑中沒有檔名,則會引發 ValueError
  • PurePath.with_suffix(suffix):將當前路徑中的檔案後綴名替換成新的後綴名。如果當前路徑中沒有後綴名,則會新增新的後綴名

os.path模組

相比 pathlib 模組,os.path 模組不僅提供了一些操作路徑字串的方法,還包含一些或者指定檔案屬性的一些方法

  • os.path.abspath(path):返回 path 的絕對路徑
  • os.path.basename(path):獲取 path 路徑的基本名稱,即 path 末尾到最後一個斜槓的位置之間的字串
  • os.path.commonprefix(list):返回 list(多個路徑)中,所有 path 共有的最長的路徑
  • os.path.dirname(path):返回 path 路徑中的目錄部分
  • os.path.exists(path):判斷 path 對應的檔案是否存在,如果存在,返回 True;反之,返回 False。和 lexists() 的區別在於,exists()會自動判斷失效的檔案鏈接(類似 Windows 系統中檔案的快捷方式),而 lexists() 卻不會
  • os.path.lexists(path):判斷路徑是否存在,如果存在,則返回 True;反之,返回 False
  • os.path.expanduser(path):把 path 中包含的 「~」 和 「~user」 轉換成使用者目錄
  • os.path.expandvars(path):根據環境變數的值替換 path 中包含的 「$name」 和 「${name}」
  • os.path.getatime(path):返回 path 所指檔案的最近存取時間(浮點型秒數)
  • os.path.getmtime(path):返迴檔案的最近修改時間(單位爲秒)
  • os.path.getctime(path):返迴檔案的建立時間(單位爲秒,自 1970 年 1 月 1 日起(又稱 Unix 時間))
  • os.path.getsize(path):返迴檔案大小,如果檔案不存在就返回錯誤
  • os.path.isabs(path):判斷是否爲絕對路徑
  • os.path.isfile(path):判斷路徑是否爲檔案
  • os.path.isdir(path):判斷路徑是否爲目錄
  • os.path.islink(path):判斷路徑是否爲鏈接檔案(類似 Windows 系統中的快捷方式)
  • os.path.ismount(path):判斷路徑是否爲掛載點
  • os.path.join(path1[, path2[, …]]):把目錄和檔名合成一個路徑
  • os.path.normcase(path):轉換 path 的大小寫和斜槓
  • os.path.normpath(path):規範 path 字串形式
  • os.path.realpath(path):返回 path 的真實路徑
  • os.path.relpath(path[, start]):從 start 開始計算相對路徑
  • os.path.samefile(path1, path2):判斷目錄或檔案是否相同
  • os.path.sameopenfile(fp1, fp2):判斷 fp1 和 fp2 是否指向同一檔案
  • os.path.samestat(stat1, stat2):判斷 stat1 和 stat2 是否指向同一個檔案
  • os.path.split(path):把路徑分割成 dirname 和 basename,返回一個元組
  • os.path.splitdrive(path):一般用在 windows 下,返回驅動器名和路徑組成的元組
  • os.path.splitext(path):分割路徑,返迴路徑名和副檔名的元組
  • os.path.splitunc(path):把路徑分割爲載入點與檔案
  • os.path.walk(path, visit, arg):遍歷path,進入每個目錄都呼叫 visit 函數,visit 函數必須有 3 個參數(arg, dirname, names),dirname 表示當前目錄的目錄名,names 代表當前目錄下的所有檔名,args 則爲 walk 的第三個參數
  • os.path.supports_unicode_filenames:設定是否可以將任意 Unicode 字串用作檔名

fnmatch模組

fnmatch 模組主要用於檔名稱的匹配,其能力比簡單的字串匹配更強大,但比使用正則表達式相比稍弱。fnmatch 模組中常用的函數有

  • fnmatch.filter(names, pattern):對 names 列表進行過濾,返回 names 列表中匹配 pattern 的檔名組成的子集合
  • fnmatch.fnmatch(filename, pattern):判斷 filename 檔名,是否和指定 pattern 字串匹配
  • fnmatch.fnmatchcase(filename, pattern):和 fnmatch() 函數功能大致相同,只是該函數區分大小寫
    +fnmatch.translate(pattern):將一個 UNIX shell 風格的 pattern 字串,轉換爲正則表達式

fnmatch 模組匹配檔名的模式使用的就是 UNIX shell 風格,其支援使用如下幾個萬用字元:

  • *:可匹配任意個任意字元
  • ?:可匹配一個任意字元
  • [字元序列]:可匹配中括號裡字元序列中的任意字元。該字元序列也支援中畫線表示法。比如 [a-c] 可代表 a、b 和 c 字元中任意一個
  • [!字元序列]:可匹配不在中括號裡字元序列中的任意字元
import fnmatch

print(fnmatch.filter(['dlsf', 'ewro.txt', 'te.py', 'youe.py'], '*.txt'))

for file in ['word.doc','index.py','my_file.txt']:
    if fnmatch.fnmatch(file,'*.txt'):
        print(file)

print([addr for addr in ['word.doc','index.py','my_file.txt','a.TXT'] if fnmatch.fnmatchcase(addr, '*.txt')])

print(fnmatch.translate('a*b.txt'))

os模組

Python的標準庫中的os模組包含普遍的操作系統功能,允許一個程式在編寫後不需要任何改動,也不會發生任何問題,就可以在Linux和Windows下執行

os模組常用屬性函數如下

  • os.sep:可以取代操作系統特定的路徑分隔符。windows下爲 「\」
  • os.name:字串指示你正在使用的平臺。比如對於Windows,它是’nt’,而對於Linux/Unix使用者,它是’posix’
  • os.linesep:字串給出當前平臺使用的行終止符。例如,Windows使用’\r\n’,Linux使用’\n’而Mac使用’\r’
  • os.curdir:返回當前目錄(’.’)
  • os.getcwd():函數得到當前工作目錄,即當前Python指令碼工作的目錄路徑
  • os.getenv():獲取一個環境變數,如果沒有返回none
  • os.putenv(key, value):設定一個環境變數值
  • os.listdir(path):返回指定目錄下的所有檔案和目錄名
  • os.mkdir(path):建立一個目錄,且該目錄的父目錄必須是已存在的
  • os.makedirs(path):建立一系列目錄,該目錄的父目錄不存在也可,會立即建立
  • os.remove(path):函數用來刪除一個檔案,不能刪除資料夾
  • os.rmdir():刪除一個目錄,只能刪除空目錄.如果刪除的目錄不存在,則會報錯
  • os.system(command):函數用來執行shell命令
  • os.chdir(dirname):改變工作目錄到dirname

tempfile模組

tempfile 模組專門用於建立臨時檔案和臨時目錄,臨時檔案和臨時目錄在程式關閉時會自動銷燬。tempfile 模組可以在 UNIX 平臺上執行良好,也可以在 Windows 平臺上執行良好。tempfile 模組中常用的函數有

  • tempfile.TemporaryFile(mode=‘w+b’, buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None):建立臨時檔案。該函數返回一個類檔案物件,也就是支援檔案 I/O
  • tempfile.NamedTemporaryFile(mode=‘w+b’, buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True):建立臨時檔案。該函數的功能與上一個函數的功能大致相同,只是它生成的臨時檔案在檔案系統中有檔名
  • tempfile.SpooledTemporaryFile(max_size=0, mode=‘w+b’, buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None):建立臨時檔案。與 TemporaryFile 函數相比,當程式向該臨時檔案輸出數據時,會先輸出到記憶體中,直到超過 max_size 纔會真正輸出到物理磁碟中
  • tempfile.TemporaryDirectory(suffix=None, prefix=None, dir=None):生成臨時目錄
  • tempfile.gettempdir():獲取系統的臨時目錄
  • tempfile.gettempdirb():與 gettempdir() 相同,只是該函數返回位元組串
  • tempfile.gettempprefix():返回用於生成臨時檔案的字首名
  • tempfile.gettempprefixb():與 gettempprefix() 相同,只是該函數返回位元組串

tempfile 模組還提供了 tempfile.mkstemp() 和 tempfile.mkdtemp() 兩個低級別的函數。上面介紹的 4 個用於建立臨時檔案和臨時目錄的函數都是高級別的函數,高級別的函數支援自動清理,而且可以與 with 語句一起使用,而這兩個低級別的函數則不支援,因此一般推薦使用高級別的函數來建立臨時檔案和臨時目錄。此外,tempfile 模組還提供了 tempfile.tempdir 屬性,通過對該屬性賦值可以改變系統的臨時目錄