Hướng dẫn toàn diện về sử dụng pathlib trong Python để thao tác hệ thống tệp
Tìm hiểu ưu điểm của pathlib trong Python so với mô-đun os bằng cách khám phá đối tượng đường dẫn, các thành phần đường dẫn và các thao tác đường dẫn phổ biến khi tương tác với hệ thống tệp.
Cho đến gần đây, thao tác với hệ thống tệp trong Python vốn nổi tiếng là khó khăn. Các lập trình viên thường gặp rắc rối với đường dẫn tệp không chính xác, dễ lỗi vì cần những chuỗi dài làm đầu vào. Ngoài ra, họ cũng báo cáo rằng mã của mình hay hỏng do không nhất quán giữa các hệ điều hành khác nhau.
May mắn thay, trong Python phiên bản 3.4, các nhà phát triển đã đưa mô-đun pathlib vào thư viện chuẩn. pathlib cung cấp một giải pháp thanh lịch để xử lý đường dẫn hệ thống tệp bằng cách tiếp cận hướng đối tượng vốn được chờ đợi từ lâu, đồng thời đảm bảo hành vi độc lập với nền tảng.
Hướng dẫn toàn diện này sẽ dạy bạn các tính năng của mô-đun pathlib để hỗ trợ tương tác hàng ngày của bạn với hệ thống tệp. Với pathlib, bạn sẽ có quy trình làm việc hiệu quả và truy xuất dữ liệu dễ dàng. pathlib đã phát triển đáng kể qua nhiều năm và chúng tôi luôn cập nhật để bạn không phải bận tâm. Hãy bắt đầu thôi.
Mô-đun os của Python so với pathlib
Trước Python 3.4, cách truyền thống hơn để xử lý đường dẫn tệp là sử dụng mô-đun os. Dù từng rất hiệu quả, mô-đun os nay đã bộc lộ dấu hiệu lạc hậu.
Chúng ta có thể cho thấy giá trị độc đáo của pathlib bằng cách xét một tác vụ phổ biến trong khoa học dữ liệu: cách tìm tất cả các tệp png trong một thư mục cho trước và toàn bộ các thư mục con của nó.
Nếu dùng mô-đun os, ta có thể viết đoạn mã sau:
import os
dir_path ="/home/user/documents"
files =[
os.path.join(dir_path, f)for f in os.listdir(dir_path)if os.path.isfile(os.path.join(dir_path, f)) and f.endswith(".png")]Được hỗ trợ bởi
Mặc dù đoạn mã này giải quyết ngay nhiệm vụ tìm tệp png, nó bộc lộ một số nhược điểm lớn của mô-đun os. Thứ nhất, mã dài và gần như khó đọc, thật đáng tiếc vì đây là thao tác khá đơn giản. Thứ hai, mã giả định người đọc hiểu về list comprehension, điều không nên coi là hiển nhiên. Thứ ba, mã dùng thao tác trên chuỗi, vốn dễ sai sót. Và ngoài tất cả điều đó, mã cũng không gọn gàng.
Nếu thay vào đó, chúng ta dùng mô-đun pathlib, mã sẽ đơn giản hơn nhiều. Như đã đề cập, pathlib cung cấp cách tiếp cận hướng đối tượng để xử lý đường dẫn hệ thống tệp. Hãy xem:
from pathlib import Path
# Create a path object
dir_path = Path(dir_path)# Find all text files inside a directory
files =list(dir_path.glob("*.png"))Được hỗ trợ bởi
Lập trình hướng đối tượng tổ chức mã quanh các đối tượng và sự tương tác của chúng, giúp mã mô-đun hóa, tái sử dụng và dễ bảo trì hơn. Nếu bạn chưa quen với lập trình hướng đối tượng, đáng để học qua khóa học Lập trình Python hướng đối tượng của chúng tôi.
Làm việc với đối tượng Path trong Python
Thư viện pathlib xoay quanh các đối tượng Path, đại diện cho đường dẫn hệ thống tệp theo cách có cấu trúc và độc lập nền tảng.
Trước đó trong hướng dẫn, chúng ta đã đưa lớp Path từ mô-đun pathlib vào không gian tên hiện tại bằng dòng mã sau:
Sau khi gọi lớp Path từ pathlib, ta có thể tạo đối tượng Path theo nhiều cách, bao gồm từ chuỗi, từ các đối tượng Path khác, từ thư mục làm việc hiện tại, và từ thư mục home.
Hãy xem lần lượt từng cách.
Tạo đối tượng đường dẫn từ chuỗi
Ta có thể tạo một đối tượng Path bằng cách truyền một chuỗi biểu diễn đường dẫn hệ thống tệp cho một biến. Điều này chuyển đổi chuỗi biểu diễn đường dẫn tệp thành một đối tượng Path.
file_path_str ="data/union_data.csv"
data_path = Path(file_path_str)Được hỗ trợ bởi
Tạo đối tượng đường dẫn từ đối tượng đường dẫn khác
Các đối tượng Path hiện có có thể đóng vai trò là khối xây dựng để tạo đường dẫn mới.
Ta làm điều này bằng cách kết hợp đường dẫn gốc, thư mục dữ liệu và tên tệp thành một đường dẫn tệp duy nhất. Cần nhớ dùng dấu gạch chéo xuôi khi thích hợp để mở rộng các đối tượng Path.
Tạo đối tượng đường dẫn từ thư mục làm việc hiện tại
Ở đây ta gán thư mục làm việc hiện tại cho biến cwd bằng phương thức Path.cwd(). Sau đó có thể truy xuất đường dẫn của thư mục làm việc hiện tại nơi tập lệnh đang chạy.
'/home/bexgboost/articles/2024/4_april/8_pathlib'Được hỗ trợ bởi
Tạo đối tượng đường dẫn từ thư mục home
Ta có thể dựng một đường dẫn bằng cách kết hợp thư mục home với các thư mục con bổ sung. Ở đây ta đang kết hợp thư mục home với các thư mục con "downloads" và "projects."
home = Path.home()
home /"downloads"/"projects"Được hỗ trợ bởi
PosixPath('/home/bexgboost/downloads/projects')Được hỗ trợ bởi
Lưu ý quan trọng: Bản thân lớp Path không thực hiện bất kỳ thao tác hệ thống tệp nào như kiểm tra hợp lệ đường dẫn, tạo thư mục hay tệp. Nó được thiết kế để biểu diễn và thao tác đường dẫn. Để thực sự tương tác với hệ thống tệp (kiểm tra tồn tại, đọc/ghi tệp), ta sẽ phải dùng các phương thức chuyên biệt của đối tượng Path và trong một số trường hợp nâng cao, cần đến mô-đun os.
Làm việc với các thành phần đường dẫn trong Python
Thuộc tính đường dẫn tệp là các đặc tính và thành phần khác nhau của một đường dẫn tệp giúp nhận diện và quản lý tệp, thư mục trong hệ thống tệp. Cũng như địa chỉ thực có nhiều phần như số nhà, thành phố, quốc gia và mã bưu chính, một đường dẫn hệ thống tệp có thể được tách thành các thành phần nhỏ hơn. pathlib cho phép chúng ta truy cập và thao tác các thành phần này bằng thuộc tính đường dẫn thông qua cú pháp chấm.
Làm việc với thư mục gốc (root)
Root là thư mục cao nhất trong hệ thống tệp. Trên hệ thống kiểu Unix, nó được biểu diễn bằng dấu gạch chéo xuôi (/). Trên Windows, thường là một ký tự ổ đĩa theo sau bởi dấu hai chấm, như C:.
image_file = home /"downloads"/"midjourney.png"
image_file.rootĐược hỗ trợ bởi
[PosixPath('/home/bexgboost/downloads'),
PosixPath('/home/bexgboost'),
PosixPath('/home'),
PosixPath('/')]Được hỗ trợ bởi
Các thao tác đường dẫn phổ biến với pathlib
Các đối tượng Path có nhiều phương thức cho phép bạn tương tác hiệu quả với thư mục và nội dung của chúng. Hãy xem cách thực hiện một số thao tác phổ biến nhất.
Liệt kê thư mục
Phương thức iterdir() cho phép bạn lặp qua tất cả tệp và thư mục con trong một thư mục. Nó đặc biệt hữu ích để xử lý tất cả tệp trong một thư mục hoặc thực hiện thao tác trên từng mục.
Vì các đối tượng Path chỉ biểu diễn đường dẫn, đôi khi bạn cần kiểm tra xem đường dẫn có tồn tại hay không bằng phương thức .exists():
Phương thức .exists() kiểm tra một đường dẫn có tồn tại hay không. Điều này hữu ích vì các đối tượng Path có thể biểu diễn tệp và thư mục có thể có hoặc không thực sự hiện diện trong hệ thống tệp.
pathlib cũng cung cấp các chức năng để tạo và xóa tệp, thư mục. Hãy xem cách thực hiện.
Phương thức mkdir()
Phương thức mkdir() tạo một thư mục mới tại đường dẫn chỉ định. Theo mặc định, nó tạo thư mục trong thư mục làm việc hiện tại.
from pathlib import Path
data_dir = Path("new_data_dir")# Create the directory 'new_data_dir' in the current working directory
data_dir.mkdir()Được hỗ trợ bởi
Phương thức mkdir(parents=True)
Phương thức mkdir(parents=True) đặc biệt hữu ích khi bạn muốn tạo một cấu trúc thư mục mà một số thư mục cha có thể chưa tồn tại. Thiết lập parents=True đảm bảo tất cả thư mục cha cần thiết sẽ được tạo trong quá trình này.
sub_dir = Path("data/nested/subdirectory")# Create 'data/nested/subdirectory', even if 'data' or 'nested' don't exist
sub_dir.mkdir(parents=True)Được hỗ trợ bởi
Hãy nhớ rằng mkdir() sẽ phát sinh ngoại lệ nếu một thư mục cùng tên đã tồn tại.
FileExistsError: [Errno 17] File exists: 'data'Được hỗ trợ bởi
Phương thức unlink()
Phương thức unlink() xóa vĩnh viễn một tệp được biểu diễn bởi đối tượng Path. Nên kiểm tra xem tệp có tồn tại trước khi chạy phương thức này để tránh lỗi.
to_delete = Path("data/prices.csv")if to_delete.exists():
to_delete.unlink()print(f"Successfully deleted {to_delete.name}")Được hỗ trợ bởi
Phương thức rmdir() xóa một thư mục trống. Hãy nhớ rằng rmdir() chỉ hoạt động để xóa thư mục trống. Cách dễ nhất để xóa một thư mục không trống là dùng thư viện shutil hoặc dùng terminal.
empty_dir = Path("new_data_dir")
empty_dir.rmdir()Được hỗ trợ bởi
Lưu ý: Hãy thận trọng khi dùng unlink() hoặc rmdir() vì kết quả là vĩnh viễn.
Thao tác đường dẫn nâng cao
Hãy chuyển sang một số khái niệm thao tác đường dẫn nâng cao và cách áp dụng chúng trong thực tế bằng pathlib.
Đường dẫn tương đối so với tuyệt đối
Chúng ta sẽ bắt đầu bằng cách hiểu sự khác nhau giữa đường dẫn tuyệt đối và tương đối, vì chúng thường xuyên xuất hiện.
Đường dẫn tương đối
Đường dẫn tương đối chỉ vị trí của tệp hoặc thư mục so với thư mục hiện tại, vì vậy mới gọi là tương đối. Chúng ngắn gọn và linh hoạt trong dự án của bạn nhưng có thể gây nhầm lẫn nếu bạn đổi thư mục làm việc.
Ví dụ, tôi có một thư mục images trong thư mục làm việc hiện tại, trong đó có tệp midjourney.png.
Đoạn mã trên hoạt động hiện tại, nhưng nếu tôi di chuyển notebook đang dùng sang vị trí khác, đoạn mã sẽ hỏng vì thư mục images không di chuyển cùng notebook.
Đường dẫn tuyệt đối
Đường dẫn tuyệt đối chỉ vị trí đầy đủ của một tệp hoặc thư mục tính từ root của hệ thống tệp. Chúng độc lập với thư mục hiện tại và cung cấp điểm tham chiếu rõ ràng cho bất kỳ người dùng nào ở bất kỳ đâu trên hệ thống.
image_absolute = Path("/home/bexgboost/articles/2024/4_april/8_pathlib/images/midjourney.png")
image_absoluteĐược hỗ trợ bởi
PosixPath('/home/bexgboost/articles/2024/4_april/8_pathlib/images/midjourney.png')Được hỗ trợ bởi
Như bạn thấy, đường dẫn tuyệt đối có thể khá dài, đặc biệt trong các dự án phức tạp có cấu trúc cây lồng nhau. Vì lý do này, đa số mọi người thích dùng đường dẫn tương đối vì ngắn hơn.
Phương thức resolve
pathlib cung cấp các phương thức để chuyển đường dẫn tương đối thành tuyệt đối với phương thức resolve().
relative_image = Path("images/midjourney.png")
absolute_image = relative_image.resolve()
absolute_imageĐược hỗ trợ bởi
PosixPath('/home/bexgboost/articles/2024/4_april/8_pathlib/images/midjourney.png')Được hỗ trợ bởi
Ta cũng có thể làm theo chiều ngược lại: Nếu có đường dẫn tuyệt đối, ta có thể chuyển nó thành đường dẫn tương đối dựa trên một thư mục tham chiếu.
relative_path = Path.cwd()
absolute_image.relative_to(relative_path)Được hỗ trợ bởi
pathlib dùng mô-đun tích hợp .glob() để tìm kiếm hiệu quả các tệp khớp với một mẫu cụ thể trong bất kỳ thư mục nào. Mô-đun này rất hữu ích khi xử lý các tệp có tên hoặc phần mở rộng tương tự nhau.
Phương thức glob hoạt động bằng cách nhận vào một chuỗi mẫu chứa ký tự đại diện và trả về một đối tượng generator cung cấp các đối tượng Path phù hợp theo nhu cầu:
*: Khớp với không hoặc nhiều ký tự.
?: Khớp với bất kỳ một ký tự đơn nào.
[]: Khớp với một dải ký tự nằm trong ngoặc vuông (ví dụ, [a-z] khớp với bất kỳ chữ thường nào).
Để minh họa, hãy thử tìm tất cả notebook Jupyter trong thư mục articles của tôi.
articles_dir = Path.home()/"articles"# Find all scripts
notebooks = articles_dir.glob("*.ipynb")# Print how many foundprint(len(list(notebooks)))Được hỗ trợ bởi
Phương thức .glob() không tìm thấy notebook nào, điều này thoạt nhìn có vẻ lạ vì tôi đã viết hơn 150 bài. Lý do là .glob() chỉ tìm trong thư mục được chỉ định, không bao gồm các thư mục con.
Ta có thể giải quyết bằng cách tìm kiếm đệ quy, khi đó ta cần dùng phương thức rglob() với cú pháp tương tự:
notebooks = articles_dir.rglob("*.ipynb")print(len(list(notebooks)))Được hỗ trợ bởi
Lần này, mã của chúng ta đã tìm thấy toàn bộ 357 tệp.
Làm việc với tệp
Như đã thấy, các đối tượng Path chỉ biểu diễn tệp chứ không thao tác trực tiếp trên chúng. Tuy vậy, chúng có một số phương thức cho các thao tác tệp phổ biến. Ta sẽ xem cách dùng trong phần này.
Đọc tệp
Đọc nội dung tệp là thao tác cơ bản trong nhiều ứng dụng Python. pathlib cung cấp các phương thức rút gọn tiện lợi để đọc tệp dưới dạng văn bản hoặc bytes thô.
Phương thức read_text() cho phép chúng ta đọc nội dung của một tệp văn bản và đóng tệp.
file= Path("file.txt")print(file.read_text())Được hỗ trợ bởi
Như thấy, phương thức write_text() sẽ ghi đè văn bản. Mặc dù không có chế độ nối thêm (append) cho write_text(), ta có thể dùng read_text() và write_text() cùng nhau để nối thêm văn bản vào cuối tệp.
old_text =file.read_text()+"\n"
final_text ="This is the final text."# Combine old and new texts and write them backfile.write_text(old_text + final_text)print(file.read_text())Được hỗ trợ bởi
write_bytes() hoạt động tương tự. Để minh họa, trước tiên hãy nhân bản ảnh midjourney.png với tên mới.
original_image = Path("images/midjourney.png")
new_image = original_image.with_stem("duplicated_midjourney")
new_imageĐược hỗ trợ bởi
PosixPath('images/duplicated_midjourney.png')Được hỗ trợ bởi
Phương thức with_stem() trả về đường dẫn tệp với tên tệp khác (mặc dù phần mở rộng giữ nguyên). Điều này cho phép ta đọc ảnh gốc và ghi nội dung của nó vào một ảnh mới.
new_image.write_bytes(original_image.read_bytes())Được hỗ trợ bởi
rename() nhận một đường dẫn đích, có thể là chuỗi hoặc đối tượng đường dẫn khác.
Để di chuyển tệp, bạn có thể dùng hàm replace(), hàm này cũng nhận đường dẫn đích:
# Define the file to be moved
source_file = Path("new_file.txt")# Define the location to put the file
destination = Path("data/new/location")# Create the directories if they don't exist
destination.mkdir(parents=True)# Move the file
source_file.replace(destination / source_file.name)Được hỗ trợ bởi
Khi bạn cần đặt trước một tên tệp để dùng sau nhưng chưa có nội dung để ghi ngay, ta có thể dùng touch để tạo một tệp trống. Phương thức này lấy cảm hứng từ lệnh touch trong Unix.
Quyền và thông tin hệ thống tệp
Mục cuối cùng, chúng ta sẽ học cách truy cập đặc tính tệp bằng phương thức .stat(). Nếu bạn quen với os, bạn sẽ nhận thấy phương thức mới này có đầu ra giống os.stat().
image_stats = original_image.stat()
image_statsĐược hỗ trợ bởi
Việc giới thiệu mô-đun pathlib trong Python 3.4 đã đơn giản hóa đáng kể thao tác với hệ thống tệp cho các nhà phát triển. Bằng cách cung cấp cách tiếp cận hướng đối tượng để xử lý đường dẫn tệp, pathlib mang đến một phương thức có cấu trúc và dễ hiểu để biểu diễn đường dẫn hệ thống tệp. pathlib cũng độc lập với nền tảng, nghĩa là pathlib xử lý dấu phân tách đường dẫn nhất quán trên các hệ điều hành khác nhau để mã của chúng ta không bị hỏng khi chạy trên máy mới. Cuối cùng, như đã thấy, pathlib cung cấp một tập hợp lớn các phương thức ngắn gọn và giàu biểu đạt cho các thao tác hệ thống tệp phổ biến.
Tôi là người sáng tạo nội dung về khoa học dữ liệu với hơn 2 năm kinh nghiệm và là một trong những tài khoản có lượng người theo dõi lớn nhất trên Medium. Tôi thích viết các bài chuyên sâu về AI và ML với chút giọng điệu mỉa mai, vì bạn cũng phải làm gì đó để chúng bớt khô khan. Tôi đã xuất bản hơn 130 bài viết và một khóa học trên DataCamp, cùng với một khóa nữa đang được thực hiện. Nội dung của tôi đã được hơn 5 triệu lượt xem, trong đó 20 nghìn người đã trở thành người theo dõi trên cả Medium và LinkedIn.
Cho đến gần đây, thao tác với hệ thống tệp trong Python vốn nổi tiếng là khó khăn. Các lập trình viên thường gặp rắc rối với đường dẫn tệp không chính xác, dễ lỗi vì cần những chuỗi dài làm đầu vào. Ngoài ra, họ cũng báo cáo rằng mã của mình hay hỏng do không nhất quán giữa các hệ điều hành khác nhau.
May mắn thay, trong Python phiên bản 3.4, các nhà phát triển đã đưa mô-đun
pathlibvào thư viện chuẩn.pathlibcung cấp một giải pháp thanh lịch để xử lý đường dẫn hệ thống tệp bằng cách tiếp cận hướng đối tượng vốn được chờ đợi từ lâu, đồng thời đảm bảo hành vi độc lập với nền tảng.Hướng dẫn toàn diện này sẽ dạy bạn các tính năng của mô-đun
pathlibđể hỗ trợ tương tác hàng ngày của bạn với hệ thống tệp. Vớipathlib, bạn sẽ có quy trình làm việc hiệu quả và truy xuất dữ liệu dễ dàng.pathlibđã phát triển đáng kể qua nhiều năm và chúng tôi luôn cập nhật để bạn không phải bận tâm. Hãy bắt đầu thôi.Mô-đun os của Python so với pathlib
Trước Python 3.4, cách truyền thống hơn để xử lý đường dẫn tệp là sử dụng mô-đun
os. Dù từng rất hiệu quả, mô-đunosnay đã bộc lộ dấu hiệu lạc hậu.Chúng ta có thể cho thấy giá trị độc đáo của
pathlibbằng cách xét một tác vụ phổ biến trong khoa học dữ liệu: cách tìm tất cả các tệppngtrong một thư mục cho trước và toàn bộ các thư mục con của nó.Nếu dùng mô-đun
os, ta có thể viết đoạn mã sau:Mặc dù đoạn mã này giải quyết ngay nhiệm vụ tìm tệp
png, nó bộc lộ một số nhược điểm lớn của mô-đunos. Thứ nhất, mã dài và gần như khó đọc, thật đáng tiếc vì đây là thao tác khá đơn giản. Thứ hai, mã giả định người đọc hiểu về list comprehension, điều không nên coi là hiển nhiên. Thứ ba, mã dùng thao tác trên chuỗi, vốn dễ sai sót. Và ngoài tất cả điều đó, mã cũng không gọn gàng.Nếu thay vào đó, chúng ta dùng mô-đun pathlib, mã sẽ đơn giản hơn nhiều. Như đã đề cập,
pathlibcung cấp cách tiếp cận hướng đối tượng để xử lý đường dẫn hệ thống tệp. Hãy xem:Lập trình hướng đối tượng tổ chức mã quanh các đối tượng và sự tương tác của chúng, giúp mã mô-đun hóa, tái sử dụng và dễ bảo trì hơn. Nếu bạn chưa quen với lập trình hướng đối tượng, đáng để học qua khóa học Lập trình Python hướng đối tượng của chúng tôi.
Làm việc với đối tượng Path trong Python
Thư viện
pathlibxoay quanh các đối tượngPath, đại diện cho đường dẫn hệ thống tệp theo cách có cấu trúc và độc lập nền tảng.Trước đó trong hướng dẫn, chúng ta đã đưa lớp
Pathtừ mô-đunpathlibvào không gian tên hiện tại bằng dòng mã sau:Sau khi gọi lớp
Pathtừpathlib, ta có thể tạo đối tượngPaththeo nhiều cách, bao gồm từ chuỗi, từ các đối tượngPathkhác, từ thư mục làm việc hiện tại, và từ thư mục home.Hãy xem lần lượt từng cách.
Tạo đối tượng đường dẫn từ chuỗi
Ta có thể tạo một đối tượng
Pathbằng cách truyền một chuỗi biểu diễn đường dẫn hệ thống tệp cho một biến. Điều này chuyển đổi chuỗi biểu diễn đường dẫn tệp thành một đối tượngPath.Tạo đối tượng đường dẫn từ đối tượng đường dẫn khác
Các đối tượng
Pathhiện có có thể đóng vai trò là khối xây dựng để tạo đường dẫn mới.Ta làm điều này bằng cách kết hợp đường dẫn gốc, thư mục dữ liệu và tên tệp thành một đường dẫn tệp duy nhất. Cần nhớ dùng dấu gạch chéo xuôi khi thích hợp để mở rộng các đối tượng
Path.Tạo đối tượng đường dẫn từ thư mục làm việc hiện tại
Ở đây ta gán thư mục làm việc hiện tại cho biến
cwdbằng phương thứcPath.cwd(). Sau đó có thể truy xuất đường dẫn của thư mục làm việc hiện tại nơi tập lệnh đang chạy.Tạo đối tượng đường dẫn từ thư mục home
Ta có thể dựng một đường dẫn bằng cách kết hợp thư mục home với các thư mục con bổ sung. Ở đây ta đang kết hợp thư mục home với các thư mục con "downloads" và "projects."
Lưu ý quan trọng: Bản thân lớp
Pathkhông thực hiện bất kỳ thao tác hệ thống tệp nào như kiểm tra hợp lệ đường dẫn, tạo thư mục hay tệp. Nó được thiết kế để biểu diễn và thao tác đường dẫn. Để thực sự tương tác với hệ thống tệp (kiểm tra tồn tại, đọc/ghi tệp), ta sẽ phải dùng các phương thức chuyên biệt của đối tượngPathvà trong một số trường hợp nâng cao, cần đến mô-đunos.Làm việc với các thành phần đường dẫn trong Python
Thuộc tính đường dẫn tệp là các đặc tính và thành phần khác nhau của một đường dẫn tệp giúp nhận diện và quản lý tệp, thư mục trong hệ thống tệp. Cũng như địa chỉ thực có nhiều phần như số nhà, thành phố, quốc gia và mã bưu chính, một đường dẫn hệ thống tệp có thể được tách thành các thành phần nhỏ hơn.
pathlibcho phép chúng ta truy cập và thao tác các thành phần này bằng thuộc tính đường dẫn thông qua cú pháp chấm.Làm việc với thư mục gốc (root)
Root là thư mục cao nhất trong hệ thống tệp. Trên hệ thống kiểu Unix, nó được biểu diễn bằng dấu gạch chéo xuôi (
/). Trên Windows, thường là một ký tự ổ đĩa theo sau bởi dấu hai chấm, nhưC:.Làm việc với thư mục cha (parent)
Thư mục cha chứa tệp hoặc thư mục hiện tại. Nó ở một cấp cao hơn so với thư mục hoặc tệp hiện tại.
Làm việc với tên tệp
Thuộc tính này trả về toàn bộ tên tệp, bao gồm phần mở rộng, dưới dạng chuỗi.
Làm việc với phần mở rộng tệp (suffix)
Thuộc tính suffix trả về phần mở rộng tệp, gồm cả dấu chấm, dưới dạng chuỗi (hoặc chuỗi rỗng nếu không có phần mở rộng).
Làm việc với phần thân tên tệp (stem)
Stem trả về tên tệp không bao gồm phần mở rộng. Làm việc với stem hữu ích khi chuyển đổi tệp sang định dạng khác.
Lưu ý: Trên máy Mac, đường dẫn tệp phân biệt chữ hoa chữ thường, vì vậy
/Users/username/Documentsvà/users/username/documentssẽ khác nhau.Thuộc tính parts của pathlib
Ta có thể dùng thuộc tính
.partsđể tách một đối tượngPaththành các thành phần của nó.Thuộc tính parents của pathlib
Thuộc tính
parents, trả về một generator, biến các thành phần này thành các đối tượngPath.Các thao tác đường dẫn phổ biến với pathlib
Các đối tượng
Pathcó nhiều phương thức cho phép bạn tương tác hiệu quả với thư mục và nội dung của chúng. Hãy xem cách thực hiện một số thao tác phổ biến nhất.Liệt kê thư mục
Phương thức
iterdir()cho phép bạn lặp qua tất cả tệp và thư mục con trong một thư mục. Nó đặc biệt hữu ích để xử lý tất cả tệp trong một thư mục hoặc thực hiện thao tác trên từng mục.Vì
iterdir()trả về một iterator, các mục sẽ được lấy theo nhu cầu khi bạn đi qua vòng lặp.Phương thức is_dir()
Phương thức
is_dir()trả vềTruenếu đường dẫn trỏ đến một thư mục,Falsenếu không.Phương thức is_file()
Phương thức
.is_file()trả vềTruenếu đường dẫn trỏ đến một tệp,Falsenếu không.Phương thức exists()
Vì các đối tượng
Pathchỉ biểu diễn đường dẫn, đôi khi bạn cần kiểm tra xem đường dẫn có tồn tại hay không bằng phương thức.exists():Phương thức .exists() kiểm tra một đường dẫn có tồn tại hay không. Điều này hữu ích vì các đối tượng
Pathcó thể biểu diễn tệp và thư mục có thể có hoặc không thực sự hiện diện trong hệ thống tệp.Tạo và xóa đường dẫn
pathlibcũng cung cấp các chức năng để tạo và xóa tệp, thư mục. Hãy xem cách thực hiện.Phương thức mkdir()
Phương thức
mkdir()tạo một thư mục mới tại đường dẫn chỉ định. Theo mặc định, nó tạo thư mục trong thư mục làm việc hiện tại.Phương thức mkdir(parents=True)
Phương thức
mkdir(parents=True)đặc biệt hữu ích khi bạn muốn tạo một cấu trúc thư mục mà một số thư mục cha có thể chưa tồn tại. Thiết lậpparents=Trueđảm bảo tất cả thư mục cha cần thiết sẽ được tạo trong quá trình này.Hãy nhớ rằng
mkdir()sẽ phát sinh ngoại lệ nếu một thư mục cùng tên đã tồn tại.Phương thức unlink()
Phương thức
unlink()xóa vĩnh viễn một tệp được biểu diễn bởi đối tượngPath. Nên kiểm tra xem tệp có tồn tại trước khi chạy phương thức này để tránh lỗi.Phương thức rmdir()
Phương thức
rmdir()xóa một thư mục trống. Hãy nhớ rằngrmdir()chỉ hoạt động để xóa thư mục trống. Cách dễ nhất để xóa một thư mục không trống là dùng thư viện shutil hoặc dùng terminal.Lưu ý: Hãy thận trọng khi dùng
unlink()hoặcrmdir()vì kết quả là vĩnh viễn.Thao tác đường dẫn nâng cao
Hãy chuyển sang một số khái niệm thao tác đường dẫn nâng cao và cách áp dụng chúng trong thực tế bằng
pathlib.Đường dẫn tương đối so với tuyệt đối
Chúng ta sẽ bắt đầu bằng cách hiểu sự khác nhau giữa đường dẫn tuyệt đối và tương đối, vì chúng thường xuyên xuất hiện.
Đường dẫn tương đối
Đường dẫn tương đối chỉ vị trí của tệp hoặc thư mục so với thư mục hiện tại, vì vậy mới gọi là tương đối. Chúng ngắn gọn và linh hoạt trong dự án của bạn nhưng có thể gây nhầm lẫn nếu bạn đổi thư mục làm việc.
Ví dụ, tôi có một thư mục images trong thư mục làm việc hiện tại, trong đó có tệp
midjourney.png.Đoạn mã trên hoạt động hiện tại, nhưng nếu tôi di chuyển notebook đang dùng sang vị trí khác, đoạn mã sẽ hỏng vì thư mục images không di chuyển cùng notebook.
Đường dẫn tuyệt đối
Đường dẫn tuyệt đối chỉ vị trí đầy đủ của một tệp hoặc thư mục tính từ root của hệ thống tệp. Chúng độc lập với thư mục hiện tại và cung cấp điểm tham chiếu rõ ràng cho bất kỳ người dùng nào ở bất kỳ đâu trên hệ thống.
Như bạn thấy, đường dẫn tuyệt đối có thể khá dài, đặc biệt trong các dự án phức tạp có cấu trúc cây lồng nhau. Vì lý do này, đa số mọi người thích dùng đường dẫn tương đối vì ngắn hơn.
Phương thức resolve
pathlibcung cấp các phương thức để chuyển đường dẫn tương đối thành tuyệt đối với phương thứcresolve().Ta cũng có thể làm theo chiều ngược lại: Nếu có đường dẫn tuyệt đối, ta có thể chuyển nó thành đường dẫn tương đối dựa trên một thư mục tham chiếu.
Globbing
Để minh họa globbing, ta có thể quay lại ví dụ ở đầu bài, nơi ta viết mã để tìm tất cả các tệp
pngtrong một thư mục nhất định.pathlibdùng mô-đun tích hợp.glob()để tìm kiếm hiệu quả các tệp khớp với một mẫu cụ thể trong bất kỳ thư mục nào. Mô-đun này rất hữu ích khi xử lý các tệp có tên hoặc phần mở rộng tương tự nhau.Phương thức glob hoạt động bằng cách nhận vào một chuỗi mẫu chứa ký tự đại diện và trả về một đối tượng generator cung cấp các đối tượng
Pathphù hợp theo nhu cầu:*: Khớp với không hoặc nhiều ký tự.?: Khớp với bất kỳ một ký tự đơn nào.[]: Khớp với một dải ký tự nằm trong ngoặc vuông (ví dụ, [a-z] khớp với bất kỳ chữ thường nào).Để minh họa, hãy thử tìm tất cả notebook Jupyter trong thư mục articles của tôi.
Phương thức
.glob()không tìm thấy notebook nào, điều này thoạt nhìn có vẻ lạ vì tôi đã viết hơn 150 bài. Lý do là.glob()chỉ tìm trong thư mục được chỉ định, không bao gồm các thư mục con.Ta có thể giải quyết bằng cách tìm kiếm đệ quy, khi đó ta cần dùng phương thức
rglob()với cú pháp tương tự:Lần này, mã của chúng ta đã tìm thấy toàn bộ 357 tệp.
Làm việc với tệp
Như đã thấy, các đối tượng
Pathchỉ biểu diễn tệp chứ không thao tác trực tiếp trên chúng. Tuy vậy, chúng có một số phương thức cho các thao tác tệp phổ biến. Ta sẽ xem cách dùng trong phần này.Đọc tệp
Đọc nội dung tệp là thao tác cơ bản trong nhiều ứng dụng Python.
pathlibcung cấp các phương thức rút gọn tiện lợi để đọc tệp dưới dạng văn bản hoặc bytes thô.Phương thức
read_text()cho phép chúng ta đọc nội dung của một tệp văn bản và đóng tệp.Với tệp nhị phân, ta có thể dùng phương thức
read_bytes().Hãy nhớ, khi dùng các phương thức
read_*, việc xử lý lỗi là quan trọng:Ghi tệp
Ghi tệp cũng dễ như đọc tệp. Để ghi tệp, ta có phương thức
write_text().Như thấy, phương thức
write_text()sẽ ghi đè văn bản. Mặc dù không có chế độ nối thêm (append) chowrite_text(), ta có thể dùngread_text()vàwrite_text()cùng nhau để nối thêm văn bản vào cuối tệp.write_bytes()hoạt động tương tự. Để minh họa, trước tiên hãy nhân bản ảnhmidjourney.pngvới tên mới.Phương thức
with_stem()trả về đường dẫn tệp với tên tệp khác (mặc dù phần mở rộng giữ nguyên). Điều này cho phép ta đọc ảnh gốc và ghi nội dung của nó vào một ảnh mới.Đổi tên và di chuyển tệp
Ngoài hàm
with_stem()để đổi stem của tên tệp,pathlibcung cấp phương thứcrename()để đổi tên hoàn chỉnh hơn.rename()nhận một đường dẫn đích, có thể là chuỗi hoặc đối tượng đường dẫn khác.Để di chuyển tệp, bạn có thể dùng hàm
replace(), hàm này cũng nhận đường dẫn đích:Tạo tệp trống
pathlibcho phép chúng ta tạo tệp trống bằng phương thứctouch:Phương thức
touchban đầu dùng để cập nhật thời gian sửa đổi của tệp, nên cũng có thể dùng với tệp đã tồn tại.Khi bạn cần đặt trước một tên tệp để dùng sau nhưng chưa có nội dung để ghi ngay, ta có thể dùng touch để tạo một tệp trống. Phương thức này lấy cảm hứng từ lệnh touch trong Unix.
Quyền và thông tin hệ thống tệp
Mục cuối cùng, chúng ta sẽ học cách truy cập đặc tính tệp bằng phương thức
.stat(). Nếu bạn quen vớios, bạn sẽ nhận thấy phương thức mới này có đầu ra giốngos.stat().Ta cũng có thể truy xuất kích thước tệp bằng cú pháp chấm.
Kết luận
Việc giới thiệu mô-đun
pathlibtrong Python 3.4 đã đơn giản hóa đáng kể thao tác với hệ thống tệp cho các nhà phát triển. Bằng cách cung cấp cách tiếp cận hướng đối tượng để xử lý đường dẫn tệp,pathlibmang đến một phương thức có cấu trúc và dễ hiểu để biểu diễn đường dẫn hệ thống tệp.pathlibcũng độc lập với nền tảng, nghĩa làpathlibxử lý dấu phân tách đường dẫn nhất quán trên các hệ điều hành khác nhau để mã của chúng ta không bị hỏng khi chạy trên máy mới. Cuối cùng, như đã thấy,pathlibcung cấp một tập hợp lớn các phương thức ngắn gọn và giàu biểu đạt cho các thao tác hệ thống tệp phổ biến.Hãy nhớ rằng,
pathlibchỉ là một trong nhiều thư viện tích hợp mạnh mẽ của Python. Bằng cách tham gia Lộ trình Nghề nghiệp Data Scientist với Python, Lộ trình Kỹ năng Lập trình Python, và Khóa Nhập môn Python cho Khoa học Dữ liệu của chúng tôi, bạn sẽ làm chủ nhiều thư viện tích hợp để trở thành một lập trình viên Python vững vàng.Cảm ơn bạn đã đọc!