Học bằng cách đọc theo thứ tự

os và pathlib — Đường dẫn file và thao tác thư mục

Học module os.path và pathlib của Python từ căn bản. Xây đường dẫn không phụ thuộc OS, liệt kê và duyệt đệ quy thư mục, và tách đường dẫn thành các phần với đối tượng Path — đều có thực hành.

Hai module xử lý đường dẫn file và thư mục — os.path cũ và pathlib mới hơn, dễ đọc hơn. Bài này đi qua xây đường dẫn không phụ thuộc OS, liệt kê và duyệt đệ quy thư mục, và tách đường dẫn thành các phần với đối tượng Path, theo thứ tự đó.

os.path — Xây đường dẫn không phụ thuộc OS

Dấu phân tách đường dẫn khác nhau theo OS. Windows dùng \ (backslash), còn Linux và macOS dùng /. Hard-code `"data/sales/2024.csv"` trực tiếp trong code chạy trên Linux và Mac, nhưng Windows có thể đọc sai đường dẫn lúc chạy.

Nếu bạn tách các phần và truyền chúng cho os.path.join("data", "sales", "2024.csv"), Python chọn dấu phân tách đúng tại chỗ dựa trên OS đang chạy.

os.path.join chuyển dấu phân tách theo OS
os.path.join( 'data', 'sales', '2024.csv')Linux / Macdata/sales/2024.csvWindowsdata\sales\2024.csv
Cùng một code Python mở rộng thành / trên Linux / Mac và \ trên Windows. Đừng nướng dấu phân tách bằng tay — đó là mẹo để portable.
HàmÝ nghĩaVí dụ
os.path.join(*parts)Nối đường dẫn với dấu phân tách OSjoin('data', 'sales') → 'data/sales'
os.path.exists(p)Đường dẫn có tồn tại khôngTrue / False
os.path.isfile(p)Có phải là file (không phải thư mục)True / False
os.path.isdir(p)Có phải là thư mụcTrue / False
os.path.basename(p)Tên file hoặc folder cuốibasename('data/x.csv') → 'x.csv'
os.path.dirname(p)Đường dẫn cha với phần cuối bỏ đidirname('data/x.csv') → 'data'
os.path.splitext(p)Tách phần mở rộngsplitext('x.csv') → ('x', '.csv')

Xây đường dẫn đến file CSV bán hàng với os.path và đọc nội dung của nó (bạn có thể thấy data/sales/2024_q1.csv và những file khác dưới panel 📂 Files bên trái).

① Hãy import os và nối ba phần đường dẫn data / sales / 2024_q1.csv thành một chuỗi với dấu phân tách OS.

② Hãy in đường dẫn đầy đủ nguyên.

③ Hãy mở data/sales/2024_q1.csv đã được preload với open(path, "r") và in 3 dòng đầu.

(Nếu chạy đúng phần giải thích sẽ xuất hiện bên dưới.)

Python Editor

Chạy code để xem đầu ra

Thực hành 2 — Tách tên và phần mở rộng với basename và splitext

Đừng nhồi tất cả vào một dòng — gán từng bước vào biến trung gian và tách tên file khỏi phần mở rộng. basename lấy tên file cuối từ đường dẫn đầy đủ, và splitext tách tên đó thành tuple (name, extension).

Đừng viết trên một dòng — đi qua biến trung gian để trích tên file và phần mở rộng.

① Hãy import os và đặt path = "data/sales/2024_q1.csv".

② Hãy lấy tên file cuối với os.path.basename(path), lưu trong filename, và in nó.

③ Hãy dùng os.path.splitext(filename) để có tuple (name, extension), lưu trong parts, và in nó.

④ Hãy unpack tuple đó vào stemsuffix, và in chúng dạng stem suffix cách bằng dấu cách.

Python Editor

Chạy code để xem đầu ra

os.listdir và os.walk — Liệt kê thư mục và duyệt đệ quy

Khi bạn muốn kéo nội dung folder vào Python, dùng os.listdir cho chỉ một cấpos.walk để đệ quy đi xuống các subfolder. os.listdir trả về danh sách tên (cả file và subfolder) trực tiếp bên trong folder bạn chỉ định, còn os.walk đi cả subtree đệ quy và yield tuple (đường dẫn hiện tại, danh sách tên subfolder, danh sách tên file) từng cấp một.

Khác biệt giữa os.listdir và os.walk
os.listdirDanh sách têntrong folder trực tiếpos.walkDuyệt đệ quymọi cấp
os.listdir chỉ cho bạn tên trực tiếp; os.walk đi xuống đệ quy qua mọi cấp. Chọn theo độ sâu bạn cần.
import os

# Một cấp: tên trực tiếp dưới 'data'
print(os.listdir("data"))
# → ['sales', 'inventory']

# Đệ quy: đi mọi thứ dưới 'data'
for dirpath, dirnames, filenames in os.walk("data"):
    print(dirpath, filenames)
# → data ['sales', 'inventory'] []
#    data/sales [] ['2024_q1.csv', '2024_q2.csv']
#    data/inventory [] ['items.json']

Hiện những gì bên trong thư mục `data/` theo hai cách — đầu tiên cấp trực tiếp, rồi đệ quy.

① Hãy import os.

② Hãy dùng os.listdir("data") để liệt kê tên trực tiếp dưới `data/` theo thứ tự đã sắp xếp (bọc với sorted để giữ thứ tự ổn định).

③ Hãy dùng os.walk("data") để đi data/ đệ quy và in một dòng mỗi cấp hiện (đường dẫn hiện tại, danh sách tên file) (bọc danh sách tên file với sorted cũng vậy).

Python Editor

Chạy code để xem đầu ra

glob — Pattern matching để gom file

Khi bạn muốn lấy chỉ file khớp điều kiện — như chỉ file có phần mở rộng `.csv` — module glob là đường ngắn nhất. Viết mục tiêu dưới dạng pattern dùng wildcard như * (chuỗi bất kỳ) hoặc ** (độ sâu bất kỳ) và bạn nhận lại danh sách đường dẫn khớp.

Wildcard của glob
*Chuỗi bất kỳ trongcùng cấp**Qua độ sâu bất kỳ(recursive=True)
* khớp chuỗi bất kỳ trong cùng cấp, ** qua bất kỳ số cấp nào (cần recursive=True).
import glob

# File CSV trực tiếp dưới data/sales
print(glob.glob("data/sales/*.csv"))
# → ['data/sales/2024_q1.csv', 'data/sales/2024_q2.csv']

# Tìm đệ quy dưới data (** + recursive=True)
print(glob.glob("data/**/*.csv", recursive=True))
# → ['data/sales/2024_q1.csv', 'data/sales/2024_q2.csv']

Wildcard ** của glob đi đôi với recursive=True

Dấu sao đôi trong glob.glob("data/**/*.csv") là wildcard qua bất kỳ số cấp nào. Nhưng không có recursive=True, nó hoạt động như * thường và sẽ không tìm gì ở folder sâu hơn. Luôn truyền tham số đó khi bạn muốn tìm đệ quy.

Lấy các file CSV trong `data/sales/` trong một lần với glob.

① Hãy import glob.

② Hãy dùng glob.glob("data/sales/*.csv") để lấy CSV dưới sales, sắp xếp với sorted, và lưu kết quả trong csv_files.

③ Hãy in mỗi đường dẫn một lần một.

④ Hãy in số lượng ở dạng Found files: ◯.

Python Editor

Chạy code để xem đầu ra

pathlib.Path — Thao tác đường dẫn hướng đối tượng

Trong khi os.path là thư viện xử lý đường dẫn dưới dạng chuỗi, từ Python 3.4 cách tiếp cận được khuyến nghị là pathlib.Path, xử lý chính đường dẫn dưới dạng đối tượng. Xây một cái với Path("data/sales/2024_q1.csv") và bạn truy cập từng phần qua thuộc tính như .parent cho folder cha, .name cho phần cuối, .stem cho tên không có phần mở rộng, và .suffix cho phần mở rộng.

Thuộc tính của đối tượng Path
Path('data/sales/2024_q1.csv').parentPath('data/sales').name'2024_q1.csv'.stem'2024_q1'.suffix'.csv'
Từ một Path bạn có thể lấy mỗi phần ra với .parent / .name / .stem / .suffix. Dễ đọc hơn gọi os.path.dirname / basename / splitext riêng.
from pathlib import Path

p = Path("data") / "sales" / "2024_q1.csv"   # Nối với toán tử /
print(p)               # data/sales/2024_q1.csv
print(p.parent)        # data/sales
print(p.name)          # 2024_q1.csv
print(p.stem)          # 2024_q1
print(p.suffix)        # .csv
print(p.exists())      # True

# Đọc nội dung (wrapper quanh with open)
print(p.read_text())   # Nội dung CSV

# Liệt kê subfolder (tương đương os.walk)
for sub in Path("data").rglob("*.csv"):
    print(sub)

`os.path` dựa trên chuỗi, `pathlib.Path` dựa trên đối tượng — chúng cung cấp cùng các thao tác. Bảng dưới ánh xạ mỗi tác vụ giữa chúng.

Bạn muốn gìPhong cách os.pathPhong cách pathlib
Nốios.path.join('data', 'x.csv')Path('data') / 'x.csv'
Folder chaos.path.dirname(p)p.parent
Tên fileos.path.basename(p)p.name
Tên không có extensionDùng os.path.splitext(p)[0]p.stem
Extensionos.path.splitext(p)[1]p.suffix
Kiểm tra tồn tạios.path.exists(p)p.exists()
Tìm đệ quyglob.glob('**/*.csv', recursive=True)Path('.').rglob('*.csv')
Đọcwith open(p) as f: f.read()p.read_text()

Chọn pathlib cho code mới

Pathlib được khuyến nghị cho code mới. Khi API thư viện cũ yêu cầu đường dẫn chuỗi (một số driver DB chẳng hạn), chuyển với str(p). os.path không đi đâu cả, nên biết cả hai ánh xạ giữ bạn thoải mái khi đọc code legacy nữa.

Dùng pathlib.Path để xử lý CSV bán hàng. Thay vì nối chuỗi trực tiếp, có cùng kết quả qua toán tử và thuộc tính của đối tượng Path.

① Hãy import class Path từ pathlib.

② Hãy xây một đối tượng Path từ ba phần data / sales / 2024_q1.csv dùng toán tử nối của Path (thay thế cho os.path.join).

③ Hãy lấy tên không có phần mở rộngphần mở rộng từ Path qua truy cập thuộc tính, và in chúng cách bằng dấu cách.

④ Hãy dùng method của Path để đọc nội dung file dưới dạng một chuỗi và in nó (cách không cần with open(...)).

Python Editor

Chạy code để xem đầu ra
QUIZ

Kiểm tra kiến thức

Hãy trả lời từng câu hỏi một.

Câu 1Cái nào là cách được khuyến nghị để xây đường dẫn không hỏng trên cả Windows hay Linux?

Câu 2Cái nào sau đây phù hợp nhất để đi mọi cấp của folder đệ quy?

Câu 3Cho p = Path("data/sales/2024_q1.csv"), giá trị của p.stem là gì?