Cảm giác “bất lực” khi chạy script Python mà không biết bao giờ xong
Bạn vừa viết xong một script Python để resize 5.000 tấm ảnh 4K hoặc crawl dữ liệu từ 10.000 URL. Bạn nhấn Enter, và… màn hình im lìm. Chỉ có một con trỏ nhấp nháy trên nền terminal đen ngòm.
Sự im lặng này cực kỳ khó chịu. Bạn không biết script đang chạy đến đâu, còn 5 phút hay 5 tiếng nữa thì xong, hay tệ hơn là nó đã bị treo (freeze) từ lúc nào. Trước đây, nhiều người thường chọn cách print() chỉ số vòng lặp để theo dõi. Tuy nhiên, việc in ra hàng nghìn dòng thông báo khiến terminal bị trôi liên tục, cực kỳ rối mắt. Thậm chí, việc gọi hàm I/O liên tục còn khiến tốc độ thực thi của script chậm lại đáng kể.
Để giải quyết vấn đề này, bạn chỉ cần một công cụ duy nhất: tqdm. Tên gọi này bắt nguồn từ tiếng Ả Rập taqadum, nghĩa là “tiến bộ”. Đây là thư viện siêu nhẹ giúp bạn thêm thanh tiến trình (progress bar) trực quan vào vòng lặp chỉ với đúng một dòng code.
Cài đặt và bắt đầu trong 30 giây
Cài đặt tqdm cực kỳ đơn giản qua pip. Hãy mở terminal và chạy lệnh:
pip install tqdm
Sau khi cài xong, chúng ta sẽ áp dụng nó vào các tình huống từ cơ bản đến thực chiến.
Cách dùng cơ bản: Bọc vòng lặp
Giả sử bạn có một vòng lặp xử lý 100 tác vụ nặng. Thay vì để nó chạy ngầm, hãy bọc hàm range() bằng tqdm().
from tqdm import tqdm
import time
# Giả lập xử lý 100 tác vụ
for i in tqdm(range(100)):
time.sleep(0.05) # Giả lập công việc tốn thời gian
Ngay lập tức, bạn sẽ thấy một thanh tiến trình hiển thị phần trăm hoàn thành, tốc độ (số item/giây) và thời gian dự kiến còn lại (ETA). tqdm tự động tính toán mọi thông số này dựa trên tốc độ xử lý thực tế.
Tùy biến thanh tiến trình chuyên nghiệp
Khi viết script cho đồng nghiệp hoặc khách hàng, bạn nên thêm mô tả để thanh tiến trình trông rõ ràng hơn. Ví dụ, bạn có thể chỉ định đơn vị đang xử lý là “file” hay “ảnh”.
for i in tqdm(range(100), desc="Đang xử lý ảnh", unit="img"):
time.sleep(0.05)
desc: Hiển thị nội dung mô tả ở phía trước thanh tiến trình.unit: Thay đổi đơn vị hiển thị (mặc định là “it” – iteration).
Kỹ thuật thực chiến: Xử lý dữ liệu lớn và File
Trong thực tế, không phải lúc nào chúng ta cũng biết trước số lượng vòng lặp. Dưới đây là hai kịch bản phổ biến nhất mà mình hay áp dụng.
Theo dõi tiến độ đọc file dung lượng lớn
Nếu bạn đang đọc một file ZIP hoặc CSV nặng 2GB, việc chờ đợi mà không thấy tiến độ rất sốt ruột. Bạn có thể cập nhật thanh tiến trình dựa trên số byte đã đọc được.
import os
file_path = "data_backup.zip"
file_size = os.path.getsize(file_path)
with tqdm(total=file_size, unit='B', unit_scale=True, desc="Đang copy file") as pbar:
with open(file_path, "rb") as f:
while True:
chunk = f.read(1024 * 1024) # Đọc từng block 1MB
if not chunk:
break
pbar.update(len(chunk))
Tham số unit_scale=True rất thông minh. Nó sẽ tự động chuyển đổi đơn vị từ Byte sang KB, MB hoặc GB để bạn dễ quan sát.
Tích hợp tqdm với Pandas
Dân Data Science chắc chắn không lạ gì cảnh ngồi chờ hàm .apply() chạy trên DataFrame hàng triệu dòng. tqdm có tích hợp sẵn cho Pandas để giải quyết sự ức chế này:
import pandas as pd
from tqdm import tqdm
# Kích hoạt tính năng hỗ trợ pandas
tqdm.pandas(desc="Đang xử lý DataFrame")
df = pd.DataFrame({'col1': range(1000000)})
# Thay vì dùng .apply(), hãy dùng .progress_apply()
df['col2'] = df['col1'].progress_apply(lambda x: x**2)
Mẹo tối ưu từ kinh nghiệm thực tế
Sau nhiều dự án tự động hóa, mình rút ra 3 bí kíp nhỏ giúp bạn sử dụng tqdm mượt mà hơn:
1. Dùng tqdm.auto cho Jupyter Notebook
Nếu bạn code trên VS Code hoặc Jupyter, thanh tiến trình mặc định đôi khi bị lỗi hiển thị thành nhiều dòng. Hãy dùng tqdm.auto. Nó sẽ tự nhận diện môi trường để hiển thị thanh tiến trình dạng HTML đẹp mắt.
from tqdm.auto import tqdm
2. Quản lý vòng lặp lồng nhau (Nested Loops)
Khi có vòng lặp con bên trong vòng lặp cha, terminal rất dễ bị loạn. Giải pháp là dùng leave=False cho vòng lặp con. Khi vòng lặp con chạy xong, nó sẽ tự biến mất để giữ cho màn hình gọn gàng.
for i in tqdm(range(5), desc="Vòng lặp cha"):
for j in tqdm(range(100), desc="Vòng lặp con", leave=False):
time.sleep(0.01)
3. Tuyệt đối không dùng print() thông thường
Nếu bạn dùng print() khi tqdm đang chạy, thanh tiến trình sẽ bị đẩy xuống và vỡ giao diện. Hãy thay thế bằng tqdm.write() để thông tin được in ra phía trên thanh tiến trình một cách ngăn nắp.
pbar = tqdm(range(10))
for i in pbar:
if i == 5:
tqdm.write("Đã hoàn thành 50% công việc!")
time.sleep(0.1)
Lời kết
tqdm là một thư viện nhỏ nhưng cải thiện trải nghiệm lập trình (UX) cực kỳ lớn. Khi xử lý những bộ dataset khổng lồ, việc nhìn thấy thanh tiến trình không chỉ giúp bạn an tâm script vẫn đang chạy, mà còn giúp bạn biết chính xác khi nào nên quay lại sau khi đi pha một tách cà phê. Hãy thử thêm tqdm vào script tiếp theo của bạn và cảm nhận sự khác biệt!
