Python Path.walk: เดินต้นไม้โฟลเดอร์แบบ pathlib โดยไม่ต้อง os.walk
น้องกายEngineering
ถ้าโปรเจกต์คุณอยู่บน Python 3.12+ และชอบ pathlib อยู่แล้ว Path.walk คือตัวเดินโฟลเดอร์ที่ไม่ต้องกระโดดไป os.walk แล้วมาต่อ path เองครับ
WHY: ลดการผสม Path กับสตริง
os.walk คืนสตริง การต่อ Path(dirpath) / name ทุกจุดทำให้โค้ดรกและพลาดง่าย เหมือนให้พิกัดร้านเป็นข้อความยาวแทนหมุดในแผนที่
from __future__ import annotations
import tempfile
import unittest
from pathlib import Path
class PathWalkTests(unittest.TestCase):
def test_walk_finds_nested_file(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
nested = root / "a" / "b"
nested.mkdir(parents=True)
target = nested / "note.txt"
target.write_text("ok", encoding="utf-8")
found = []
for dirpath, dirnames, filenames in root.walk():
for name in filenames:
found.append(dirpath / name)
self.assertIn(target.resolve(), [p.resolve() for p in found])
def test_top_down_can_prune(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
(root / "keep").mkdir()
(root / "skip").mkdir()
(root / "keep" / "x.txt").write_text("1", encoding="utf-8")
(root / "skip" / "y.txt").write_text("2", encoding="utf-8")
seen = []
for dirpath, dirnames, filenames in root.walk():
if dirpath == root:
dirnames[:] = [d for d in dirnames if d != "skip"]
for name in filenames:
seen.append(name)
self.assertEqual(seen, ["x.txt"])
if __name__ == "__main__":
unittest.main()
หมายเหตุ: อย่าสับสนกับ os.fwalk / dir_fd ในบทความเช้า — อันนี้เป็น API ของ pathlib สำหรับโค้ดที่อยู่บน Path อยู่แล้ว
Recap
- ใช้
Path.walkเมื่อโปรเจกต์เป็น pathlib + Python 3.12+ - ตัดโฟลเดอร์ไม่ต้องการด้วยการแก้
dirnamesตอน top-down - โปรเจกต์เก่ากว่า 3.12 ยังใช้
os.walkได้ตามเดิม