1. 程式人生 > >你還在用 os.path?快來感受一下 pathlib 給你帶來的便捷吧!

你還在用 os.path?快來感受一下 pathlib 給你帶來的便捷吧!

相比常用的 os.path而言,pathlib 對於目錄路徑的操作更簡介也更貼近 Pythonic。但是它不單純是為了簡化操作,還有更大的用途

概述

pathlib 是Python內建庫,Python 文件給它的定義是 Object-oriented filesystem paths(面向物件的檔案系統路徑)。pathlib 提供表示檔案系統路徑的類,其語義適用於不同的作業系統。路徑類在純路徑之間劃分,純路徑提供純粹的計算操作而沒有I / O,以及具體路徑,它繼承純路徑但也提供I / O操作。

聽起來有點繞?那就對了,畢竟這是直譯過來的,但這並不影響我們喜愛它。 我們通過幾個例子來了解它吧

舉個栗子

相對於 os 模組的 path 方法,Python3 標準庫 pathlib 模組的 Path 對路徑的操作會更簡單。

獲取當前檔案路徑

使用 os 模組時,有兩種方法可以直接獲取當前檔案路徑:

import os

value1 = os.path.dirname(__file__)
value2 = os.getcwd()
print(value1)
print(value2)
複製程式碼

pathlib 獲取當前檔案路徑應該怎麼寫呢?

官方文件給出了建議 插眼傳送

動手試一試

import pathlib

value1 = pathlib.Path.cwd()
print
(value1) 複製程式碼

它是如何實現的

文件中有介紹,它以 os.getcwd() 的形式將路徑返回。我們去原始碼中一探究竟(Pycharm 編輯器快捷鍵 ctrl+滑鼠左鍵點選即可跟進指定物件)

原來它是對 os 模組中一些物件進行了封裝,看 cwd 的註釋: Return a new path pointing to the current working directory
意為:返回指向當前工作目錄的新路徑。

看起來也沒什麼特別的,但是為什麼官方特意將它推出呢?

其他的封裝

pathlib 封裝了很多的 os path ,文件中有寫明,如:

# 關係說明
 os.path.expanduser() --> pathlib.Path.home()
 
 os.path.expanduser() --> pathlib.Path.expanduser()
 
 os.stat() --> pathlib.Path.stat()
 
 os.chmod() --> pathlib.Path.chmod()
複製程式碼

官網文件截圖:

詳細請檢視官方文件:插眼傳送

再舉幾個栗子

剛才的案例並不能說明什麼,只是讓我們瞭解到 pathlib 的構成,接下來讓我們感受一下它帶給我們的便捷。

獲取上層/上層目錄

也就是獲取它爺爺的名字

os 模組的寫法為:

import os

print(os.path.dirname(os.path.dirname(os.getcwd())))
複製程式碼

如果用 pathlib 來實現:

import pathlib

print(pathlib.Path.cwd().parent.parent)

複製程式碼

parent 就完事了,這是不是更貼近 Pythonic ? 像寫英語一樣寫程式碼。

如果你只需要找到它爸爸,那就使用一次:

import pathlib

print(pathlib.Path.cwd().parent)

複製程式碼

你還可以繼續往祖輩上找:

import pathlib

print(pathlib.Path.cwd().parent.parent.parent)
複製程式碼

相對與之前 os 模組使用的多層 os.path.dirname,使用 parent 是不是便捷很多?

路徑拼接

如果你要在它爺爺輩那裡拼接路徑,那麼你需要寫這麼長一串程式碼:

import os

print(os.path.join(os.path.dirname(os.path.dirname(os.getcwd())), "關注", "微信公眾號", "【進擊的", "Coder】"))

複製程式碼

當你用 pathlib 的時候,你一定能夠感受到快樂:

import pathlib

parts = ["關注", "微信公眾號", "【進擊的", "Coder】"]
print(pathlib.Path.cwd().parent.parent.joinpath(*parts))

複製程式碼

而且你還可以通過增加或減少 parent 的數量,來實現它祖輩的調節,美哉。

PurePath

上面的操作大部分都通過 pathlib 中的 Path 實現,其實它還有另一個模組 PurePath。

PurePath 是一個純路徑物件,純路徑物件提供了實際上不訪問檔案系統的路徑處理操作。有三種方法可以訪問這些類,我們也稱之為flavor。

上面這句話來自於官方文件,聽起來還是有點繞,我們還是通過栗子來了解它吧

PurePath.match

讓我們來判斷一下,當前檔案路徑是否有符合 '*.py' 規則的檔案

import pathlib

print(pathlib.PurePath(__file__).match('*.py'))
複製程式碼

很顯然,我們編寫程式碼的 coder.py 就符合規則,所以輸出是 True。

為什麼我要拿這個來舉例呢?再深入想一下 pathlib.PurePath 後面能夠跟著 match,那說明它應該是個物件,而不是一個路徑字串。為了驗證這個想法,把程式碼改一改:

import pathlib
import os


os_path = os.path.dirname(__file__)
pure_path = pathlib.PurePath(__file__)
print(os_path, type(os_path))
print(pure_path, type(pure_path))
print(pathlib.PurePath(__file__).match('*.py'))

複製程式碼

列印通過 os.path 獲取當前路徑的結果,得出一個路徑字串;而通過 pathlib.Pure 則獲得的是一個 PurePosixPath 物件,並且得到的路徑包括了當前檔案 coder.py

這就有點懸疑了, PurePosixPath 究竟是什麼?

pathlib 可以操作兩種檔案系統的路徑,一種是 Windows 檔案系統,另一種稱為非 Windows 檔案系統,對應的物件是 pathlib.PurePosixPathPureWindowsPath,不過不用擔心,這些類並非是指定在某些作業系統上執行才能夠使用,無論你執行的是哪個系統,都可以例項化所有這些類,因為它們不提供任何進行系統呼叫的操作。

不提供任何進行系統呼叫的操作,這又是什麼?真是越聽越深了

文件在最開始給出了這麼一段描述:

Pure paths are useful in some special cases; for example: If you want to manipulate Windows paths on a Unix machine (or vice versa). You cannot instantiate a WindowsPath when running on Unix, but you can instantiate PureWindowsPath. You want to make sure that your code only manipulates paths without actually accessing the OS. In this case, instantiating one of the pure classes may be useful since those simply don’t have any OS-accessing operations.

翻譯:純路徑在某些特殊情況下很有用; 例如: 如果要在Unix計算機上操作Windows路徑(反之亦然)。WindowsPath在Unix上執行時無法例項化,但可以例項化PureWindowsPath。 您希望確保您的程式碼僅操作路徑而不實際訪問作業系統。在這種情況下,例項化其中一個純類可能很有用,因為那些只是沒有任何作業系統訪問操作。

還附上了一張圖:

一下子也不是很理解,這是什麼意思。不要緊,繼續往下看。

對應關係

通過以上的例子我們可以感受到,它不僅封裝了 os.path 相關常用方法,還集成了 os 的其他模組,比如建立資料夾 Path.mkdir。

如果你擔心記不住,沒關係的,文件一直都在。並且文件給我們列出了對應關係表

基本用法

Path.iterdir()  # 遍歷目錄的子目錄或者檔案

Path.is_dir()  # 判斷是否是目錄

Path.glob()  # 過濾目錄(返回生成器)

Path.resolve()  # 返回絕對路徑

Path.exists()  # 判斷路徑是否存在

Path.open()  # 開啟檔案(支援with)

Path.unlink()  # 刪除檔案或目錄(目錄非空觸發異常)

基本屬性

Path.parts  # 分割路徑 類似os.path.split(), 不過返回元組

Path.drive  # 返回驅動器名稱

Path.root  # 返回路徑的根目錄

Path.anchor  # 自動判斷返回drive或root

Path.parents  # 返回所有上級目錄的列表

改變路徑

Path.with_name()  # 更改路徑名稱, 更改最後一級路徑名

Path.with_suffix()  # 更改路徑字尾

拼接路徑

Path.joinpath()  # 拼接路徑

Path.relative_to()  # 計算相對路徑

測試路徑

Path.match()  # 測試路徑是否符合pattern

Path.is_dir()  # 是否是檔案

Path.is_absolute()  # 是否是絕對路徑

Path.is_reserved()  # 是否是預留路徑

Path.exists()  # 判斷路徑是否真實存在

其他方法

Path.cwd()  # 返回當前目錄的路徑物件

Path.home()  # 返回當前使用者的home路徑物件

Path.stat()  # 返回路徑資訊, 同os.stat()

Path.chmod()  # 更改路徑許可權, 類似os.chmod()

Path.expanduser()  # 展開~返回完整路徑物件

Path.mkdir()  # 建立目錄

Path.rename()  # 重新命名路徑

Path.rglob()  # 遞迴遍歷所有子目錄的檔案

pathlib 回顧

通過上面的幾個例子,我們對 pathlib 應該有一個大體的瞭解,接下來再回顧一下官方給 pathlib 庫的定義:

This module offers classes representing filesystem paths with semantics appropriate for different operating systems. Path classes are divided between pure paths, which provide purely computational operations without I/O, and concrete paths, which inherit from pure paths but also provide I/O operations.

釋義:pathlib 提供表示檔案系統路徑的類,其語義適用於不同的作業系統。路徑類在純路徑之間劃分,純路徑提供純粹的計算操作而沒有I / O,以及具體路徑,它繼承純路徑但也提供I / O操作。

回顧剛才這張圖,重新理解 pathlib

如果你以前從未使用過這個模組,或者只是不確定哪個類適合您的任務,那麼Path很可能就是您所需要的。它為程式碼執行的平臺例項化一個具體路徑。

總結:pathlib 不單純是對 os 中一些模組或方法進行封裝,而是為了相容不同的作業系統,它為每類作業系統定義了介面。你希望在UNIX機器上操作Windows的路徑,然而直接操作是做不到的,所以為你建立了一套介面 PurePath,你可以通過介面來實現你的目的(反之亦然)