0
0
Lập trình
Admin Team
Admin Teamtechmely

So sánh Python Logging và Print: Tại sao Logging Lại Tốt Hơn

Đăng vào 1 ngày trước

• 10 phút đọc

Giới thiệu

Chúng ta đều đã từng ở trong tình huống này: bạn đang viết mã Python, có điều gì đó không hoạt động như mong đợi, và phản xạ đầu tiên của bạn là rải rác một vài câu lệnh print(). Một câu lệnh print("Đến đây") để xem hàm có chạy hay không, hoặc print("x:", x) để kiểm tra giá trị của một biến. Thông thường, điều này có thể giúp bạn, ít nhất là cho đến khi nó không còn hiệu quả.

Phương pháp của tôi cũng vậy. print() là bạn đồng hành của tôi, luôn sẵn sàng để cho tôi một cái nhìn nhanh.

Nhưng có một điều: print() chỉ ổn khi bạn đang thử nghiệm, không phải khi bạn đang xây dựng. Khi mã của bạn phát triển, bạn cần nhiều hơn là những kiểm tra nhanh chóng, bạn cần ngữ cảnh, cấu trúc và sự bền vững.

Đó là lúc mô-đun logging của Python xuất hiện. Logging không chỉ đơn thuần là một print() tốt hơn; nó là một bộ công cụ hoàn chỉnh giúp biến đổi quá trình gỡ lỗi. Nó cho bạn biết chương trình của bạn đang làm gì, khi nào và - quan trọng nhất - tại sao mọi thứ lại sai.

Tại sao print() không đủ

Ban đầu, print() có vẻ rất hữu ích. Chỉ cần thả một dòng trong mã của bạn, chạy nó, và voilà, bạn thấy điều gì đang xảy ra. Nhưng ngay khi dự án của bạn phát triển vượt ra ngoài một kịch bản nhỏ, những vấn đề bắt đầu xuất hiện.

Dưới đây là những điểm yếu của print():

  • Không có mức độ quan trọng: Mọi thông điệp đều giống nhau. Dù đó là một kiểm tra vô hại hay một lỗi nghiêm trọng, print("có gì đó sai") không cho bạn biết mức độ lo lắng của bạn nên như thế nào.

  • Không có dấu thời gian hay ngữ cảnh: Khi nào lỗi xảy ra? Ở phần nào của mã? print() sẽ không nói. Tất cả những gì bạn nhận được chỉ là văn bản thô, nhanh chóng trở nên vô dụng khi mọi thứ trở nên phức tạp.

  • Không có tính bền vững: Ngay khi chương trình của bạn kết thúc, dấu vết gỡ lỗi quý giá của bạn biến mất. Nếu điều gì đó hỏng vào ban đêm, bạn thức dậy mà không có bằng chứng nào về điều đã xảy ra.

  • Khó để dọn dẹp: Không có gì làm rối mã nguồn nhanh hơn hàng tá câu lệnh print(). Bình luận chúng, xóa chúng, hoặc quên một cái trong sản xuất là một cơn đau đầu mà tất cả chúng ta đã từng trải qua.

  • Không thể mở rộng: print() có thể ổn khi bạn đang lập trình một mình, nhưng trong các hệ thống sản xuất hoặc dự án nhóm, nó đơn giản là không đủ. Các nhật ký là một ngôn ngữ chung; print() chỉ là tiếng ồn.

print() giống như một chiếc đèn pin, giúp bạn trong một căn phòng tối, nhưng sẽ không chiếu sáng toàn bộ con đường khi bạn đang điều hướng một khu rừng. Đối với điều đó, bạn cần một thứ được xây dựng cho công việc: logging.

Những gì Logging mang lại

Chuyển từ print() sang logging giống như bước ra khỏi bóng tối và vào một phòng điều khiển. Đột nhiên, tôi không chỉ thấy những thông điệp thô, mà tôi nhận được thông tin có tổ chức và có ý nghĩa.

Dưới đây là lý do tại sao logging tạo ra sự khác biệt lớn:

  • Mức độ nhật ký: Không phải tất cả các thông điệp đều xứng đáng nhận được sự chú ý như nhau. Với logging, tôi có thể đánh dấu một cái gì đó là DEBUG khi tôi đang theo dõi luồng, sử dụng INFO cho các sự kiện bình thường, tăng WARNING cho các vấn đề tiềm ẩn, và giữ ERRORCRITICAL cho các vấn đề thực sự. Nó giống như việc chuyển từ văn bản phẳng sang một hệ thống cảnh báo có ưu tiên.

  • Khả năng cấu hình: Chán ngấy việc bị ngập trong các thông điệp gỡ lỗi? Với logging, tôi không phải xóa bất cứ điều gì, tôi chỉ cần thay đổi mức độ nhật ký. Một cài đặt điều khiển mức độ chi tiết tôi thấy, liệu tôi có muốn mọi thứ trong quá trình phát triển hay chỉ cảnh báo trong sản xuất.

  • Ngữ cảnh: Nhật ký không chỉ là các thông điệp; chúng đi kèm với dấu thời gian, tên mô-đun, thậm chí là số dòng. Điều đó có nghĩa là khi có điều gì đó hỏng, tôi không chỉ thấy đã xảy ra, tôi biết khi nàoở đâu.

  • Tính bền vững: Không giống như print(), nhật ký có thể tồn tại lâu dài. Chúng có thể được ghi vào các tệp, xoay vòng hàng ngày, hoặc được gửi đến các công cụ giám sát. Nếu kịch bản của tôi gặp sự cố vào lúc 2 giờ sáng, tôi thức dậy với một dấu vết thay vì một bảng điều khiển trống rỗng.

  • Tính chuyên nghiệp: Cuối cùng, logging là tiêu chuẩn. Các đội ngũ, khung làm việc, và hệ thống sản xuất dựa vào nó vì nó có thể mở rộng. Đó là sự khác biệt giữa việc gỡ lỗi bằng băng keo và kỹ thuật với kỷ luật.

Logging không chỉ làm cho việc gỡ lỗi dễ dàng hơn, mà còn cho mã của bạn một giọng nói, một giọng nói có thể thì thầm những chi tiết nhỏ hoặc phát ra cảnh báo khi có điều gì đó sai.

Bắt đầu với Logging

Tin tốt là gì? Việc chuyển từ print() sang logging dễ hơn bạn nghĩ. Bạn không cần phải đại tu toàn bộ dự án của mình, bạn có thể bắt đầu nhỏ với chỉ một vài dòng cấu hình.

Dưới đây là cách đơn giản nhất để bắt đầu:

python Copy
import logging

logging.basicConfig(level=logging.DEBUG)

logging.debug("Đây là một thông điệp gỡ lỗi")
logging.info("Ứng dụng đang chạy suôn sẻ")
logging.warning("Có điều gì đó có vẻ không ổn, nhưng vẫn chạy")
logging.error("Có điều gì đó sai")
logging.critical("Chúng ta đang gặp nguy hiểm!")

Chạy đoạn mã đó, và bạn sẽ thấy đầu ra với các mức độ nhật ký tự động được đính kèm, giống như:

text Copy
DEBUG:root:Đây là một thông điệp gỡ lỗi
INFO:root:Ứng dụng đang chạy suôn sẻ
WARNING:root:Có điều gì đó có vẻ không ổn, nhưng vẫn chạy
ERROR:root:Có điều gì đó sai
CRITICAL:root:Chúng ta đang gặp nguy hiểm!

Chú ý rằng bạn nhận được nhiều ngữ cảnh hơn so với các câu lệnh print() đơn giản.

Với print(), tất cả những gì bạn thấy chỉ là văn bản. Với logging, bạn ngay lập tức biết đó là một lỗi, không chỉ là một thông điệp ngẫu nhiên khác. Và với một thay đổi cấu hình, bạn có thể bao gồm các dấu thời gian, tên tệp, và thậm chí số dòng.

Đó là một sự chuyển dịch nhỏ trong cách bạn viết mã, nhưng nó mang lại lợi ích ngay lần đầu tiên bạn phải theo dõi một vấn đề.

Tùy chỉnh Nhật ký

Sức mạnh thực sự đến từ việc tùy chỉnh. Bằng cách điều chỉnh chỉ một vài cài đặt, tôi có thể biến các thông điệp nhật ký đơn giản thành thứ hữu ích hơn nhiều.

Thay đổi định dạng

Bạn muốn biết không chỉ đã xảy ra, mà còn khi nàoở đâu? Điều đó đơn giản như điều chỉnh định dạng:

python Copy
import logging

logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s"
)

logging.warning("Có thể có điều gì đó không ổn ở đây")

Bây giờ mỗi nhật ký cho tôi biết dấu thời gian, mức độ nghiêm trọng, tệp, và số dòng:

text Copy
2025-09-18 08:34:06,157 - WARNING - example03.py:8 - Có thể có điều gì đó không ổn ở đây

Đột nhiên, các nhật ký của tôi cảm thấy như một máy ghi âm đen cho mã của tôi.

Ghi nhật ký vào tệp

In ra bảng điều khiển thì ổn cho việc gỡ lỗi nhanh chóng, nhưng nếu chương trình của bạn chạy qua đêm hoặc trên một máy chủ? Bạn sẽ muốn ghi nhật ký vào một tệp:

python Copy
logging.basicConfig(
    filename="app.log",
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s"
)

logging.info("Ứng dụng đã khởi động")

Điều này tạo ra một tệp app.log với:

text Copy
2025-09-18 08:35:58,314 - INFO - Ứng dụng đã khởi động

Bằng cách này, tôi có thể quay lại sau và theo dõi chính xác những gì đã xảy ra.

Xoay vòng nhật ký

Tất nhiên, một tệp có thể phát triển không kiểm soát nếu ứng dụng của bạn chạy trong vài tuần hoặc vài tháng. Đó là lúc nhật ký xoay vòng xuất hiện:

python Copy
import logging
from logging.handlers import RotatingFileHandler

handler = RotatingFileHandler("app.log", maxBytes=2000, backupCount=5)
logging.basicConfig(
    handlers=[handler],
    level=logging.DEBUG,
    format="%(asctime)s - %(levelname)s - %(message)s"
)

logging.debug("Điều này sẽ được xoay vòng khi tệp quá lớn")

Bây giờ, một khi app.log đạt khoảng 2 KB, nó sẽ chuyển sang một tệp mới, giữ lại lịch sử mà không làm đầy ổ cứng của tôi.

Các Logger khác nhau cho các mô-đun khác nhau

Trong các dự án lớn hơn, việc có các logger riêng biệt giúp mỗi phần của mã có thể “nói lên chính nó.”

python Copy
import logging

logger = logging.getLogger("data_processor")
logger.setLevel(logging.DEBUG)

# Thêm một bộ xử lý bảng điều khiển
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

logger.info("Dòng dữ liệu đã bắt đầu")

Thay vì mọi thứ bị gộp lại vào “root,” tôi biết chính xác mô-đun nào đã sản xuất thông điệp nào.

Thực hành tốt nhất

Đến thời điểm này, logging đã trở thành công cụ ưa thích của tôi, nhưng như bất kỳ công cụ nào, dễ dàng để sử dụng sai. Ngay từ đầu, tôi đã mắc vài lỗi khiến nhật ký của tôi trở thành một cơn lũ tiếng ồn hoặc một mối nguy cơ tiềm tàng cho bảo mật.

Dưới đây là một số bài học tôi đã học được theo cách khó khăn:

Chọn mức độ nhật ký phù hợp

Không phải mọi thông điệp đều xứng đáng được cảnh báo đỏ nhấp nháy. Sử dụng DEBUG cho thông tin nội bộ chi tiết, INFO cho các hoạt động bình thường, WARNING cho các vấn đề tiềm ẩn, ERROR cho các vấn đề, và CRITICAL khi hệ thống gặp phải vấn đề nghiêm trọng. Chọn lựa khôn ngoan giữ cho nhật ký của bạn dễ đọc và có ý nghĩa.

Tránh việc ghi nhật ký quá mức

Tôi đã từng ghi nhật ký mọi vòng lặp trong một vòng lặp xử lý hàng nghìn mục. Kết quả? Các thông điệp lỗi thực sự của tôi bị chôn vùi dưới một đống tiếng ồn. Ghi nhật ký một cách chiến lược: đủ để theo dõi những gì đang xảy ra, nhưng không quá nhiều để những thứ quan trọng bị mất.

Không ghi nhật ký dữ liệu nhạy cảm

Mật khẩu, mã thông báo API, thông tin người dùng cá nhân, hãy giữ chúng ra khỏi nhật ký của bạn. Nó thật hấp dẫn khi đổ mọi thứ cho việc gỡ lỗi, nhưng một khi nhật ký kết thúc trong các tệp, máy chủ, hoặc công cụ giám sát, dữ liệu nhạy cảm đó có thể trở thành một rủi ro.

Sử dụng nhật ký có cấu trúc khi mở rộng

Khi ứng dụng của bạn phát triển vượt ra ngoài một kịch bản đơn lẻ, nhật ký văn bản thông thường có thể trở nên lộn xộn. Nhật ký có cấu trúc, giúp tìm kiếm, lọc và phân tích nhật ký dễ dàng hơn với các công cụ như Elasticsearch, Logstash, Kibana hoặc các dịch vụ tập hợp nhật ký đám mây. Đây là nơi mà logging phát triển từ một trợ giúp gỡ lỗi đơn giản trở thành một giải pháp giám sát hoàn chỉnh.

Logging mạnh mẽ nhất khi nó được thực hiện một cách chu đáo. Làm đúng, nó giống như có một máy ghi âm chuyến bay cho mã của bạn, ghi lại đủ thông tin để giúp bạn hiểu điều gì đã xảy ra, mà không làm bạn choáng ngợp bởi chi tiết hoặc tiết lộ bí mật.

Kết luận

Với logging, mã của tôi có cấu trúc, ký ức và một giọng nói có thể cho tôi biết không chỉ đã sai, mà còn khi nàoở đâu.

Sự chuyển đổi từ print sang logging không cần phải quá sức. Bạn không cần phải làm chủ các bộ xử lý, bộ định dạng, và xoay vòng ngay lập tức. Chỉ cần bắt đầu nhỏ: thay thế một vài câu lệnh print() bằng logging.info() hoặc logging.error(). Thêm một dấu thời gian. Lưu nhật ký vào một tệp. Từng bước một, bạn sẽ xây dựng thói quen giúp cho các dự án của bạn dễ duy trì hơn và các phiên gỡ lỗi ít đau đớn hơn.

Và đây là sự thật: lần đầu tiên điều gì đó gặp sự cố trong sản xuất và nhật ký của bạn giải thích bình tĩnh điều đã xảy ra, bạn sẽ tự hỏi làm thế nào bạn có thể sống mà không có chúng.

Vậy hãy tiếp tục, để print() nghỉ hưu cho những thử nghiệm nhanh của bạn, và để logging đảm nhận khi điều đó thực sự quan trọng. Tương lai của bạn sẽ cảm ơn bạn.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào