您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關Python3文件操作中是如何使用pathlib模塊的,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
在本教程中,你將了解如何使用 pathlib 模塊操作目錄和文件的名稱。學習如何讀取和寫入文件,拼接路徑和操作底層文件系統的新方法,以及如何列出文件并迭代它們的一些示例。
大多人處理文件用的最多的還是 os 模快吧,比如下面這樣的操作:
>>> path.rsplit('\\', maxsplit=1)[0]
或者寫出下面這樣長長的代碼
>>> os.path.isfile(os.path.join(os.path.expanduser('~'), 'realpython.txt'))
使用 pathlib 模塊,可以使代碼使用優雅,可讀和 Pythonic 代碼重寫上面的兩個示例,如:
>>> path.parent >>> (pathlib.Path.home() / 'realpython.txt').is_file()
Python 文件路徑處理問題
由于許多不同的原因,使用文件和與文件系統交互很重要。 最簡單的情況可能只涉及讀取或寫入文件,但有時候會有更復雜的任務。也許你需要列出給定類型的目錄中的所有文件,查找給定文件的父目錄,或者創建一個尚不存在的唯一文件名。
一般情況,Python 使用常規文本字符串表示文件路徑。一般在使用 os,glob 和 shutil 等庫的時候會使用到路徑拼接的操作,使用os模塊拼接起來顯得略顯復雜,以下示例僅需要三個 import 語句來將所有文本文件移動到歸檔目錄:
import glob import os import shutil for file_name in glob.glob('*.txt'): new_path = os.path.join('archive', file_name) shutil.move(file_name, new_path)
使用常規的字符串去拼接路徑是可以的,但是由于不同的操作系統使用的分隔符不同,這樣就容易出現問題,所以一般我們使用最多的還是使用 os.path.join()。
Python 3.4 中引入了 pathlib 模塊(PEP 428)再一次的優化了路徑的拼接。使用 pathlib 庫的 Path 方法,可以將一個普通的字符串轉換為 pathlib.Path 對象類型的路徑。
早期,其他軟件包仍然使用字符串作為文件路徑,但從 Python 3.6 開始,pathlib 模塊在整個標準庫中得到支持,部分原因是由于增加了文件系統路徑協議。 如果你堅持使用傳統的 Python,那么 Python 2 也有一個可用的向后移植。
ok,說了那么多下面讓我們看看 pathlib 如何在實踐中發揮作用。
創建路徑
這里我們首先要知道兩個用法,先看代碼:
from pathlib import Path
你真正需要知道的是 pathlib.Path 類。創建路徑有幾種不同的方式。首先,有類方法,如 .cwd(當前工作目錄)和 .home(用戶的主目錄):
from pathlib import Path now_path = Path.cwd() home_path = Path.home() print("當前工作目錄",now_path,type(now_path)) print("home目錄",home_path,type(home_path))
輸出內容:
當前工作目錄 /Users/chennan/pythonproject/demo <class 'pathlib.PosixPath'> home目錄 /Users/chennan <class 'pathlib.PosixPath'>
可以發現路徑格式為 pathlib.PosixPath 這是在 unix 系統下的顯示。在不同的系統上顯示的格式也是不一樣,在 windows 系統會顯示為 WindowsPath。但是不管什么顯示類型,都不影響后面的操作。
前面我們提到過可以通過把字符串類型的路徑,轉換為 Pathlib.Path 類型的路徑,經過測試發現在 Python3.4 以后很多模塊以及支持該格式的路徑。不用轉為成字符串使用了。比起 os.path.join 拼接路徑的方式,pathlib 使用起來更加的方便,使用示例如下:
import pathlib DIR_PATH = pathlib.Path("/Users/chennan/CDM") print(DIR_PATH,type(DIR_PATH))
輸出內容:
/Users/chennan/CDM <class 'pathlib.PosixPath'>
通過 “/” 我們就可以對路徑進行拼接了,怎么樣是不是很方便呢。
讀文件和寫文件
在我們使用 open 來操作文件讀寫操作的時候,不僅可以使用字符串格式的路徑,對于 pathlib 生成的路徑完全可以直接使用:
path = pathlib.Path.cwd() / 'test.md' with open(path, mode='r') as fid: headers = [line.strip() for line in fid if line.startswith('#')] print('\n'.join(headers))
或者在 pathlib 的基礎使用 open,我們推薦使用下面的方式:
import pathlib DIR_PATH = pathlib.Path("/Users/chennan/CDM") / "2000" / "hehe.txt" with DIR_PATH.open("r") as fs: data = fs.read() print(data)
這樣寫的好處就是 open 里面我們不需要再去傳入路徑了,直接指定文件讀寫模式即可。實際上這里的 open 方法,底層也是調用了 os.open 的方法。使用哪種方式看個人的喜好。
pathlib 還提供幾種文件的讀寫方式:
可以不用再使用 with open 的形式即可以進行讀寫。
.read_text(): 找到對應的路徑然后打開文件,讀成str格式。等同open操作文件的"r"格式。 .read_bytes(): 讀取字節流的方式。等同open操作文件的"rb"格式。 .write_text(): 文件的寫的操作,等同open操作文件的"w"格式。 .write_bytes(): 文件的寫的操作,等同open操作文件的"wb"格式。
使用 resolve 可以通過傳入文件名,來返回文件的完整路徑,使用方式如下:
import pathlib py_path =pathlib.Path("superdemo.py") print(py_path.resolve())
輸出:
/Users/chennan/pythonproject/demo/superdemo.py
需要注意的是 “superdemo.py” 文件要和我當前的程序文件在同一級目錄。
選擇路徑的不同組成部分
pathlib 還提供了很多路徑操作的屬性,這些屬性可以選擇路徑的不用部位,如:
.name: 可以獲取文件的名字,包含拓展名。
.parent: 返回上級文件夾的名字。
.stem: 獲取文件名不包含拓展名。
.suffix: 獲取文件的拓展名。
.anchor: 類似盤符的一個東西。
import pathlib now_path = pathlib.Path.cwd() / "demo.txt" print("name",now_path.name) print("stem",now_path.stem) print("suffix",now_path.suffix) print("parent",now_path.parent) print("anchor",now_path.anchor)
輸出內容如下:
name demo.txt stem demo suffix .txt parent /Users/chennan/pythonproject/demo anchor /
移動和刪除文件
當然 pathlib 還可以支持文件其他操作,像移動,更新,甚至刪除文件,但是使用這些方法的時候要小心因為,使用過程不用有任何的錯誤提示即使文件不存在也不會出現等待的情況。
使用 replace 方法可以移動文件,如果文件存在則會覆蓋。為避免文件可能被覆蓋,最簡單的方法是在替換之前測試目標是否存在。
import pathlib destination = pathlib.Path.cwd() / "target" source = pathlib.Path.cwd() / "demo.txt" if not destination.exists(): source.replace(destination)
但是上面的方法存在問題就是,在多個進程多 destination 進行的操作的時候就會現問題,可以使用下面的方法避免這個問題。也就是說上面的方法適合單個文件的操作。
import pathlib destination = pathlib.Path.cwd() / "target" source = pathlib.Path.cwd() / "demo.txt" with destination.open(mode='xb') as fid: #xb表示文件不存在才操作 fid.write(source.read_bytes())
當 destination文件存在的時候上面的代碼就會出現 FileExistsError 異常。
從技術上講,這會復制一個文件。 要執行移動,只需在復制完成后刪除源即可。
使用 with_name 和 with.shuffix 可以修改文件名字或者后綴。
import pathlib source = pathlib.Path.cwd() / "demo.py" source.replace(source.with_suffix(".txt")) #修改后綴并移動文件,即重命名
可以使用 .rmdir() 和 .unlink() 來刪除文件。
import pathlib destination = pathlib.Path.cwd() / "target" source = pathlib.Path.cwd() / "demo.txt" source.unlink()
幾個 pathlib 的使用例子
統計文件個數
我們可以使用.iterdir方法獲取當前文件下的所以文件.
import pathlib from collections import Counter now_path = pathlib.Path.cwd() gen = (i.suffix for i in now_path.iterdir()) print(Counter(gen))
輸出內容:
Counter({'.py': 16, '': 11, '.txt': 1, '.png': 1, '.csv': 1})
通過配合使用 collections 模塊的 Counter 方法,我們獲取了當文件夾下文件類型情況。
前面我們說過 glob 模塊點這里了解【cnblogs.com/c-x-a/p/926】,同樣的 pathlib 也有 glob 方法和 rglob 方法,不同的是 glob 模塊里的 glob 方法結果是列表形式的,iglob 是生成器類型,在這里 pathlib 的 glob 模塊返回的是生成器類型,然后 pathlib 還有一個支持遞歸操作的 rglob 方法。
下面的這個操作我通過使用 glob 方法,設定規則進行文件的匹配。
import pathlib from collections import Counter gen =(p.suffix for p in pathlib.Path.cwd().glob('*.py')) print(Counter(gen))
展示目錄樹
下一個示例定義了一個函數 tree(),該函數的作用是打印一個表示文件層次結構的可視樹,該樹以一個給定目錄為根。因為想列出其子目錄,所以我們要使用 .rglob() 方法:
import pathlib from collections import Counter def tree(directory): print(f'+ {directory}') for path in sorted(directory.rglob('*')): depth = len(path.relative_to(directory).parts) spacer = ' ' * depth print(f'{spacer}+ {path.name}') now_path = pathlib.Path.cwd() if __name__ == '__main__': tree(now_path)
其中 relative_to 的方法的作用是返回 path 相對于 directory 的路徑。
parts 方法可以返回路徑的各部分。例如:
import pathlib now_path = pathlib.Path.cwd() if __name__ == '__main__': print(now_path.parts)
返回:
('/', 'Users', 'chennan', 'pythonproject', 'demo')
獲取文件最后一次修改時間
iterdir(),.glob()和.rglob()方法非常適合于生成器表達式和列表理解。
使用stat()方法可以獲取文件的一些基本信息,使用.stat().st_mtime可以獲取文件最后一次修改的信息
import pathlib now_path = pathlib.Path.cwd() from datetime import datetime time, file_path = max((f.stat().st_mtime, f) for f in now_path.iterdir()) print(datetime.fromtimestamp(time), file_path)
甚至可以使用類似的表達式獲取上次修改的文件內容
import pathlib from datetime import datetime now_path =pathlib.Path.cwd() result = max((f.stat().st_mtime, f) for f in now_path.iterdir())[1] print(result.read_text())
.stat().st_mtime 會返回文件的時間戳,可以使用 datetime 或者 time 模塊對時間格式進行進一步轉換。
其他內容
關于 pathlib.Path 格式路徑轉換為字符串類型
因為通過 pathlib 模塊操作生成的路徑,不能直接應用字符串的一些操作,所以需要轉換成字符串,雖然可以使用 str() 函數進行轉換,但是安全性不高,建議使用 os.fspath() 方法,因為如果路徑格式非法的,可以拋出一個異常。str()就不能做到這一點。
拼接符號”/”背后的秘密
/ 運算符由 __truediv__ 方法定義。 實際上,如果你看一下 pathlib 的源代碼,你會看到類似的東西。
class PurePath(object): def __truediv__(self, key): return self._make_child((key,))
關于Python3文件操作中是如何使用pathlib模塊的就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。