路徑小幫手 - pathlib
- Learn with Shin
- Jul 27, 2021
- 4 min read
Updated: Jul 28, 2021
人生好難,要怎麼樣才能找到正確的路徑...😔
咳咳 ~今天不是要討論這麼沈重的話題啦 😅
是說,在寫Python的時候,有時候會需要讀取(或寫入)檔案吧?
譬如說,我有一個文字檔案,想要讀到 我的Python 程式裡面。這時我們需要提供該檔案的路徑,像這樣👇:
Python就可以根據你提供的路徑找到你要的檔案 。
那麼,這個路徑還有什麼特色呢?這個今天我們就來看一下Python路徑的眉眉角角 😀。
路徑(Path)
首先稍微談一下這個所謂的檔案路徑吧。
根據你的電腦的作業系統(Operating System),路徑的長相會不一樣。
Windows系統的Path長得像這樣:
C:\user\docs\my_file.txt
Mac或Linux系統的Path長得像這樣:
/home/user/docs/my_file.txt
有注意到分隔的斜線是相反的🧐?
如果你是使用Windows的話,其實在Python中當我們提供路徑的時候,是可以把斜線反過來的。所以下面這樣的路徑是OK的:
with open("C:/user/docs/my_file.txt") as f:
...
不然的話,你可能得用像這樣的寫法(加一個r 在string之前)來提供原始字串(raw string literals):
with open(r"C:\user\docs\myFile.txt") as f:
...
因為這個反斜線(blackslash)在一些程式語言包括Python,代表的是一個Escape Character,基本上有它特殊的意義及作用,今天先不多做敘述。
絕對路徑 & 相對路徑
再來,當我們在提供路徑時,基本上有兩種選項:
絕對路徑(Absolute Path)
相對路徑(Relative Path)
絕對路徑就是你的檔案的完整路徑(Full Path),像我們上面看到的Mac的路徑:
/home/user/docs/my_file.txt
清楚易懂,對吧?
至於相對路徑就稍微有一點麻煩了 🤨。
它是根據你目前執行指令的資料夾地點(Current Working Directory),與所指定的File的相對位置。
Say what???
舉個例子來看,假設下面是你的資料夾構造(Folder Structure):
/directory_1
/directory_2
+ my_program.py
+ my_program_2.py
+ my_file.txt
假設我在my_program.py裡面有這一段code:
然後你在directory_2這個folder底下執行:
$cd directory_2
$python my_program.py
嗯,這樣應該是不會有任何問題。Everything works!
這裡我給的路徑 "my_file.txt",就是一個相對路徑。Python會自動去試著辨別你給的路徑是絕對路徑或相對路徑。
相對於我執行的位置(directory_2),我可以在同一個資料夾中找到myFile.txt。(你也可以寫作 "./my_file.txt" ,這個小點點(.)指的就是現在所在的資料夾)
可是瑞凡...今天如果你跑到directory_1,然侯去執行my_program.py的話...
$cd .. # go up one directory to directory_1
$python directory_2/my_program.py
Oh no~ 你會得到一個像這樣的Error:
FileNotFoundError: [Errno 2] No such file or directory: 'my_file.txt'
因為相對於你當前的位置(directory_1),my_file.txt並不存在。
我們為了方便(或只是懶惰)常常會使用相對路徑。那麼,該如何才能更有彈性的從任何地方都可以執行你的程式,不受限於你的Current Working Directory呢?
我們稍後會再回來看這一點。
OK,說了那麼多,今天主要想跟大家一起來看一下Python內建的pathlib模組(注意這是python 3.4 版本之後才有的喔),來幫我們更俐落的處理路徑問題!
路徑物件
以往我們看到路徑的表現方式是用單純的string(像是"/home/user/docs/myFile.txt")。
pathlib則是將路徑以物件的方式呈現(簡單來說就是一個叫做路徑的特殊資料類型)。透過這個路徑物件,我們能更輕鬆直覺的做各種路徑的操作~🙂
來看以下的例子(假設我們在directory_2下執行my_program.py):
Path.cwd( ) 會產生一個路徑物件來代表Current Working Directory。
你可以利用這個路徑物件在你的File System中遊走,並生成新的路徑物件。
如果要往上一個directory,利用 .parent這個屬性;
如果要往下,利用 "/" 這個符號加上你的資料夾或檔案的名字。
承接上面的例子:
話說,當我們用print來顯示物件的時候,印出來的是物件的string的表示方式(String Representation),看起來就像是一般的文字路徑。但是不要忘了,他可還是一個路徑物件。
利用這個路徑物件,我們還可以直接讀取檔案內容喔:
這邊用到的是.read_text這個method,看起來是不是相當清爽~😃
接下來再介紹一個很有用的功能:
有時候,我們會需要在一個資料夾裡面做檔案的搜尋,譬如說:找出所有的csv檔案。
利用路徑物件的.glob功能,我們可以快速的做到這一件事,不需要自己寫for loop喔。
.glob("*.csv") 會找出所有結尾為 .csv的檔案,而且每一個檔案都已經是路徑物件了喔 😀。意思就是,你可以取出當中的任何一個檔案,然後直接用.read_text。
注意這裡glob會給我們一個generator,因此我們用list功能把它做個轉換成實體的List。
路徑轉換
接下來看一下先前提到的,如何更有彈性的利用相對路徑讓你可以從任何地方來執行程式。
我們可以利用__file__這一個內建的variable來做到這一點。__file__會根據你當下執行的地點(current working directory),給我們檔案(這裡指的是my_program_2.py)相對的位置 。
this_file_path.parent指的是my_program_2.py存在的資料夾(也就是directory_2)。因為我們知道,my_file.txt跟my_program_2.py是在同一個資料夾內。
這樣一來,不論你是在directory_2下面,
$cd directory_2
$python my_program_2.py
或是回到directory_1來執行,
$cd .. # go up one directory to directory_1
$python directory_2/my_program_2.py
都不會有任何問題👍🏻!
另外,如果你想要拿到絕對路徑的String的話,你可以利用 .resolve這個method。
結論
今天我們針對Python的路徑跟大家簡單做了以下的介紹:
何謂路徑
絕對路徑以及相對路徑的概念
pathlib的路徑物件
如何提供有彈性的路徑
Python的pathlib還有許多其他的功能,包括做檔案的移動、拷貝或刪除、以及許多的小幫手功能像是檢驗路徑是否存在,是否為檔案或是文件夾,還有檔名的擷取等等...詳細的官方介紹可以參考這裡。
善用pathlib,幫助我們寫出更易讀且符合現代Python標準(pythonic)的Code喔 ~😉
Comments