为什么你应该开始习惯使用 pathlib
幾年前,當(dāng)我發(fā)現(xiàn) Python 的新 pathlib 模塊時(shí),我最初認(rèn)為它是 os.path 模塊的一個(gè)稍微笨拙和不必要的面向?qū)ο蟀姹尽N义e(cuò)了。Python 的 pathlib 模塊實(shí)際上很棒!
在本文中,我將嘗試在pathlib上向你推銷(xiāo)。我希望本文將激勵(lì)你在任何需要使用 Python 中的文件時(shí)使用 Python 的 pathlib 模塊。
os.path 笨拙
os.path 模塊一直是我們用來(lái)處理 Python 中的路徑的庫(kù)。你需要的東西差不多都包含在內(nèi)了,但有時(shí)它會(huì)很顯得笨重。
你應(yīng)該像這樣導(dǎo)入它?
?
import os.pathBASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) TEMPLATES_DIR = os.path.join(BASE_DIR, 'templates')還是像這樣?
?
from os.path import abspath, dirname, joinBASE_DIR = dirname(dirname(abspath(__file__))) TEMPLATES_DIR = join(BASE_DIR, 'templates')或者,該 join 函數(shù)的命名過(guò)于籠統(tǒng),我們還可以這樣做:
?
from os.path import abspath, dirname, join as joinpathBASE_DIR = dirname(dirname(abspath(__file__))) TEMPLATES_DIR = joinpath(BASE_DIR, 'templates')但是,我覺(jué)得這些都有點(diǎn)尷尬。我們將字符串傳遞到返回字符串的函數(shù)中,然后又將其傳遞給返回字符串的其他函數(shù)。這些字符串剛好可以表示路徑,但它們?nèi)匀恢皇亲址?/p>
當(dāng)多個(gè)函數(shù)嵌套時(shí),os.path 中字符串進(jìn)字符串出類(lèi)的函數(shù)非常笨拙,我們需要從內(nèi)向外來(lái)閱讀代碼。如果我們可以把這些嵌套的函數(shù)調(diào)用轉(zhuǎn)換成鏈?zhǔn)椒椒ㄕ{(diào)用,這不是很好嗎?
有了 pathlib 模塊,我們就可以了!
?
from pathlib import PathBASE_DIR = Path(__file__).resolve().parent.parent TEMPLATES_DIR = BASE_DIR.joinpath('templates')os.path 模塊需要函數(shù)嵌套,但是 pathlib 模塊的 path 類(lèi)允許我們鏈?zhǔn)讲僮?Path 對(duì)象上的方法和屬性,以獲得等效的路徑表示。
也許你在想:等等,這些路徑對(duì)象不是一回事:它們是對(duì)象,不是路徑字符串!不急,我們將稍后來(lái)討論這個(gè)問(wèn)題(提示:這些字符串幾乎可以與路徑字符串互換使用)。
os 模塊臃腫
Python 經(jīng)典模塊 os.path 只用于處理路徑。一旦你真的想通過(guò)路徑做一些事情(例如創(chuàng)建一個(gè)目錄),你就需要用到另一個(gè) Python 模塊,通常也是 os 下的模塊。
os 模塊有許多用于處理文件和目錄的工具,比如:mkdir、getcwd、chmod、stat、remove、rename 和 rmdir。還有 chdir、link、wald、listdir、makedirs、rename、remvedirs、unlink (與remove相同) 以及 symlink。此外,還有一大堆與文件系統(tǒng)完全無(wú)關(guān)的東西:fork、getenv、putenv、environ、getlogin 和 system。還有很多在這里沒(méi)有羅列的東西。
Python 的 os 模塊什么都能做一點(diǎn);它有點(diǎn)像是系統(tǒng)相關(guān)東西的大雜燴。盡管 os 模塊中有很多不錯(cuò)的東西,但有時(shí)也可能很難找到你要的東西:比如你想在 os模塊中查找與路徑或文件系統(tǒng)相關(guān)的內(nèi)容,則需要進(jìn)一步挖掘。
pathlib 模塊用 path 對(duì)象上的方法替換了許多這些與文件系統(tǒng)相關(guān)的 os 功能。
以下代碼創(chuàng)建了src/_pypackages_目錄,并將 .editorconfig 文件重命名為 src/.editorconfig:
?
import os import os.pathos.makedirs(os.path.join('src', '__pypackages__'), exist_ok=True) os.rename('.editorconfig', os.path.join('src', '.editorconfig'))使用 Path 對(duì)象執(zhí)行相同的操作:
?
from pathlib import PathPath('src/__pypackages__').mkdir(parents=True, exist_ok=True) Path('.editorconfig').rename('src/.editorconfig')注意,由于鏈?zhǔn)椒椒?#xff0c;pathlib 代碼將路徑放在第一位!
正如 Python 之禪所說(shuō),“名稱(chēng)空間是一個(gè)很棒的想法,讓我們做更多的事情”。os 模塊是一個(gè)非常大的名稱(chēng)空間,里面有一堆東西。pathlib.path 類(lèi)是一個(gè)比 os 模塊更小、目標(biāo)更明確的命名空間。此路徑命名空間中的方法返回路徑對(duì)象,允許方法鏈?zhǔn)讲僮鞫皇亲址唇邮降那短缀瘮?shù)調(diào)用。
別忘了還有 GLOB 模塊!
os 和 os.path 模塊并不是 Python 標(biāo)準(zhǔn)庫(kù)中唯一與文件路徑/文件系統(tǒng)相關(guān)的功能模塊。glob 模塊是另一個(gè)處理路徑相關(guān)的模塊。
我們可以使用 glob.glob 函數(shù)查找與特定模式匹配的文件:
?
from glob import globtop_level_csv_files = glob('*.csv') all_csv_files = glob('**/*.csv', recursive=True)新的 pathlib 模塊同樣包括類(lèi)似 glob 的功能。
?
from pathlib import Pathtop_level_csv_files = Path.cwd().glob('*.csv') all_csv_files = Path.cwd().rglob('*.csv')當(dāng)重度使用 pathlib 之后,你可能會(huì)完全忘記 glob 模塊的存在: PATH 對(duì)象已經(jīng)提供了的所有 glob 模塊所具備的功能。
pathlib 讓簡(jiǎn)單變得更簡(jiǎn)單
pathlib 模塊將許多復(fù)雜的情況變得簡(jiǎn)單,但它也可以使一些簡(jiǎn)單的事情變得更簡(jiǎn)單。
需要讀取一個(gè)或多個(gè)文件中的所有文本?
你可以使用 with 語(yǔ)句塊打開(kāi)文件、讀取其內(nèi)容然后關(guān)閉文件:
?
from glob import globfile_contents = [] for filename in glob('**/*.py', recursive=True):with open(filename) as python_file:file_contents.append(python_file.read())或者,你可以用 Path 對(duì)象的 read_text 方法,在一行代碼中用列表解析功能將文件內(nèi)容讀取到一個(gè)新列表中:
?
from pathlib import Pathfile_contents = [path.read_text()for path in Path.cwd().rglob('*.py') ]如果我需要寫(xiě)入文件呢?
你可以使用 open 上下文管理器:
?
with open('.editorconfig') as config:config.write('# config goes here')或者使用 write_text 方法:
?
Path('.editorconfig').write_text('# config goes here')如果你更喜歡使用 open (無(wú)論是作為上下文管理器還是其他方式),你同樣可以在 PATH 對(duì)象上使用 OPEN 方法:
?
from pathlib import Pathpath = Path('.editorconfig') with path.open(mode='wt') as config:config.write('# config goes here')或者,從 Python3.6 開(kāi)始,你甚至可以將 PATH 對(duì)象傳遞給內(nèi)置的 open 函數(shù):
?
from pathlib import Pathpath = Path('.editorconfig') with open(path, mode='wt') as config:config.write('# config goes here')PATH 對(duì)象讓你的代碼更加明確
以下三個(gè)變量指向什么?它們的值代表什么?
?
person = '{"name": "Trey Hunner", "location": "San Diego"}' pycon_2019 = "2019-05-01" home_directory = '/home/trey'這些變量中的每一個(gè)都指向一個(gè)字符串。
這些字符串表示不同的東西:一個(gè)是 JSON blob,一個(gè)是日期,還有一個(gè)是文件路徑。
以下是這些對(duì)象更有用的表示:
?
from datetime import date from pathlib import Pathperson = {"name": "Trey Hunner", "location": "San Diego"} pycon_2019 = date(2019, 5, 1) home_directory = Path('/home/trey')JSON 對(duì)象可以反序列化到字典,日期在本地使用 datetime.date 對(duì)象表示,文件系統(tǒng)路徑現(xiàn)在可以使用 pathlib.path 對(duì)象統(tǒng)一表示。
使用 Path 對(duì)象可以使代碼更加明確。如果要表示日期,則可以使用 Date 對(duì)象。如果試圖表示文件路徑,則可以使用 Path 對(duì)象。
我并非面向?qū)ο缶幊痰膱?jiān)定擁護(hù)者。類(lèi)增加了另一層抽象層,而抽象有時(shí)會(huì)增加更多的復(fù)雜性無(wú)法保持簡(jiǎn)單化。但是 pathlib.Path 類(lèi)是一個(gè)有用的抽象。它也正在迅速成為一個(gè)普遍接受的抽象。
感謝 PEP519,文件路徑對(duì)象現(xiàn)在成為使用路徑的標(biāo)準(zhǔn)。在 Python3.6 中,內(nèi)置的 open 函數(shù)以及 os、shutil 和 os.path 模塊中的各種函數(shù)都可以與 pathlib.path 對(duì)象一起正常工作。你可以從現(xiàn)在開(kāi)始使用 pathlib,而不需要改動(dòng)大多數(shù)使用路徑的代碼!
pathlib 還缺少什么?
雖然 pathlib 是偉大的,但它并不是包羅萬(wàn)象的。我無(wú)意中發(fā)現(xiàn)了一些缺失的特性,我希望 pathlib 模塊能夠包括這些特性。
我注意到的第一個(gè)缺陷是 pathlib.Path 的方法中缺少與 shutil 等效的功能。
雖然可以將路徑對(duì)象(和類(lèi)似路徑的對(duì)象)傳遞給高層的 shutil 函數(shù)進(jìn)行復(fù)制/刪除/移動(dòng)文件和目錄的操作,但是 Path 對(duì)象上沒(méi)有與此等效的方法。
因此,要復(fù)制文件,你仍然需要執(zhí)行如下操作:
?
from pathlib import Path from shutil import copyfilesource = Path('old_file.txt') destination = Path('new_file.txt') copyfile(source, destination)同樣也沒(méi)有與 os.chdir 等效的 pathlib 功能。
這意味著如果需要更改當(dāng)前工作目錄,仍需要導(dǎo)入 chdir:
?
from pathlib import Path from os import chdirparent = Path('..') chdir(parent)也沒(méi)有與 os.walk 函數(shù)等價(jià)的 pathlib 函數(shù)。盡管你可以很容易地使用 pathlib 創(chuàng)建你自己的 walk 式函數(shù)。
我希望 pathlib.Path 對(duì)象最終可以包含其中一些缺失操作的方法。盡管存在這些缺失的特性,我仍然覺(jué)得使用“ pathlib 系”比使用“ os.path 系”更易于管理。
你是否應(yīng)該始終使用 pathlib?
從Python3.6開(kāi)始,pathlib.Path 對(duì)象幾乎可以在任何已經(jīng)使用路徑字符串的地方工作。因此,如果你使用的是Python3.6(或更高版本),我認(rèn)為沒(méi)有理由不使用 pathlib。
如果您使用的是 python 3 的早期版本, 則可以將 path 對(duì)象始終包裝在 str 調(diào)用中, 以便在需要轉(zhuǎn)義填充字符串的地方獲取相應(yīng)的字符串返回。雖然有點(diǎn)尷尬, 但還是管用:
?
from os import chdir from pathlib import Pathchdir(Path('/home/trey')) # Python 3.6+ 版 chdir(str(Path('/home/trey'))) # 早期的 Python 3 版不管你使用的是哪個(gè)版本的 Python3,我都建議你嘗試一下 pathlib。
什么?你還在用 Python2 ?好吧,萬(wàn)能的 PyPI 上有個(gè)第三方工具 pathlib2 模塊是一個(gè)選擇,現(xiàn)在,你可以在任何版本的 Python 上使用 pathlib 啦!。
用 pathlib 讓我的代碼更具可讀性。現(xiàn)在,我處理文件的大多數(shù)代碼都默認(rèn)使用 pathlib,我建議你也這樣做。如果可以用 pathlib,則盡量用吧。
原文:https://treyhunner.com/2018/12/why-you-should-be-using-pathlib/
作者:愛(ài)吃魚(yú)de大貓
鏈接:https://www.jianshu.com/p/ae194371cf7c
來(lái)源:簡(jiǎn)書(shū)
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
總結(jié)
以上是生活随笔為你收集整理的为什么你应该开始习惯使用 pathlib的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Roberta-wwm-ext-larg
- 下一篇: Lex-BERT:超越FLAT的中文NE