攝影或3C

Python用 pathlib.Path 優雅處理檔案與路徑:從 os 過渡的實用指南(Jupyter 可直接執行);from pathlib import Path

前言

  • 傳統上我們用 os、os.path 來處理路徑;現代 Python 推薦使用 pathlib.Path。
  • Path 是物件導向、跨平台且可讀性高。以下以「對照+範例」方式帶你快速上手,所有程式碼皆為可複製的程式碼區塊,適合在 Jupyter 逐格執行。

一、建立與檢視路徑(os vs Path)

# os.path 寫法
import os
p_os = os.path.join("data", "images", "cat.jpg")
print(p_os, type(p_os))

# pathlib.Path 寫法 / 直覺拼接跨平台自動處理分隔符
from pathlib import Path
p = Path("data") / "images" / "cat.jpg"
print(p, str(p), p.as_posix(), type(p))

輸出:

p, str(p), p.as_posix(), type(p)

路徑分隔符:

二、拆解與操作路徑

# %%
# os.path 寫法
import os
p_str = "data/images/cat.jpg"
dirname = os.path.dirname(p_str)
basename = os.path.basename(p_str)
stem, ext = os.path.splitext(basename)
print("dir:", dirname, "name:", basename, "stem:", stem, "ext:", ext)


# %%
# Path 寫法屬性一目了然
from pathlib import Path
p = Path("data/images/cat.jpg")
print("parent:", p.parent)
print("name:", p.name)
print("stem:", p.stem)
print("suffix:", p.suffix)
print("parents:", list(p.parents)[:3])  # 多層父目錄
print("換副檔名:", p.with_suffix(".png"))
print("加子路徑:", p.parent / "thumbs" / p.name)

輸出:

三、存在性與建立資料夾

# os 寫法
import os
print(os.path.exists("data"), os.path.isfile("data"), os.path.isdir("data"))
if not os.path.exists("data/output"):
    os.makedirs("data/output", exist_ok=True)
    
# Path 寫法
from pathlib import Path
d = Path("data")
print(d.exists(), d.is_file(), d.is_dir())
(d / "output").mkdir(parents=True, exist_ok=True)

輸出:

四、讀寫文字檔

# os + open
text_path = "data/output/notes.txt"
with open(text_path, "w", encoding="utf-8") as f:
    f.write("Hello\n")
with open(text_path, "a", encoding="utf-8") as f:
    f.write("World\n")
with open(text_path, "r", encoding="utf-8") as f:
    print(f.read())

# Path 快捷read_text / write_text / open
from pathlib import Path
text_path = Path("data/output/notes.txt")
text_path.parent.mkdir(parents=True, exist_ok=True)
text_path.write_text("Hello\nWorld\n", encoding="utf-8")
print(text_path.read_text(encoding="utf-8"))

輸出:

五、走訪與過濾檔案(glob/rglob)

# os.walk
import os
all_py = []
for root, dirs, files in os.walk(r"D:\Temp"):
    for f in files:
        if f.endswith(".py"):
            all_py.append(os.path.join(root, f))
print(all_py[:5])


# Path  glob非遞迴 rglob遞迴
from pathlib import Path
print(list(Path(r"D:\Temp").glob("*.txt"))[:5])     # 當層 *.txt
print(list(Path(r"D:\Temp").rglob("*.py"))[:5])     # 遞迴 *.py

輸出:

六、複製、移動、刪除(搭配 shutil)

# os + shutil
import os, shutil
src = "data/input/a.txt"
dst = "data/output/a.txt"
os.makedirs(os.path.dirname(dst), exist_ok=True)
shutil.copy2(src, dst)  # 複製並保留 metadata
os.remove(dst)          # 刪除

# Path + shutil
from pathlib import Path
import shutil
src = Path("data/input/a.txt")
dst = Path("data/output/a.txt")
dst.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src, dst)
dst.unlink()            # 刪除檔案等同 os.remove
# 刪資料夾Path("some_dir").rmdir()  # 空資料夾
# 刪非空資料夾shutil.rmtree(Path("some_dir"))

七、檔案資訊與美化時間

# os.stat
import os, time
st = os.stat("data/images/cat.jpg")
print("size:", st.st_size, "mtime:", time.ctime(st.st_mtime))

# Path.stat + datetime
from pathlib import Path
from datetime import datetime
p = Path("data/images/cat.jpg")
st = p.stat()
print("size:", st.st_size)
print("mtime:", datetime.fromtimestamp(st.st_mtime).strftime("%Y-%m-%d %H:%M:%S"))

八、目前工作目錄與絕對路徑

# os
import os
print(os.getcwd())
print(os.path.abspath("."))

# Path
from pathlib import Path
print(Path.cwd())
print(Path(".").resolve())

九、切換目錄(臨時,確保切回來)

import os
from pathlib import Path

cwd = Path.cwd()
try:
    os.chdir("data")
    print("now in:", Path.cwd())
finally:
    os.chdir(cwd)
    print("back to:", Path.cwd())

十、展開家目錄與環境變數

# os
import os
print(os.path.expanduser("~/projects"))
print(os.path.expandvars("%USERPROFILE%/projects" if os.name == "nt" else "$HOME/projects"))

# Path + os
from pathlib import Path
import os
print(Path("~/projects").expanduser())
print(Path(os.path.expandvars("$HOME/projects")))

十一、相對路徑與比較

# %%
# os.path.relpath兩者不需父子關係也可計算
import os
print(os.path.relpath("/a/b/c", "/a"))  # 'b/c'

# %%
# Path.relative_to要求左邊包含右邊否則會丟例外
from pathlib import Path
print(Path("/a/b/c").relative_to("/a"))  # Path('b/c')

輸出:

十二、小專案實作:合併資料夾內所有 .txt 到一個檔案

from pathlib import Path

src_dir = Path("data/texts")
out = Path("data/merged.txt")
out.parent.mkdir(parents=True, exist_ok=True)

with out.open("w", encoding="utf-8") as fout:
    for txt in sorted(src_dir.rglob("*.txt")):
        fout.write(f"--- {txt.name} ---\n")
        fout.write(txt.read_text(encoding="utf-8"))
        fout.write("\n\n")

print("Written:", out.resolve())

十三、Path 小抄(最常用的幾行)

from pathlib import Path

# 建立路徑
p = Path("base") / "sub" / "file.txt"

# 路徑組件
print(p.parent, p.name, p.stem, p.suffix)

# 建資料夾
(Path("logs") / "today").mkdir(parents=True, exist_ok=True)

# 讀寫檔案
Path("note.txt").write_text("hello", encoding="utf-8")
print(Path("note.txt").read_text(encoding="utf-8"))

# 走訪
files = list(Path("base").rglob("*.py"))
print(files[:5])

結語

  • 新專案優先使用 pathlib.Path;它讓程式更直覺、跨平台更安心。
  • 仍可與 os、shutil 等共用:需要字串時用 str(Path物件),需要系統呼叫時用 os。
  • 先記住三件事就能快速上手:用 / 拼路徑、用 read_text/write_text 存取、用 glob/rglob 走訪。

推薦hahow線上學習python: https://igrape.net/30afN

儲蓄保險王

儲蓄險是板主最喜愛的儲蓄工具,最喜愛的投資理財工具則是ETF,最喜愛的省錢工具則是信用卡