ویژگی تصویر

معرفی کتابخانه logging در پایتون

  /  پایتون   /  کتابخانه logging در پایتون
بنر تبلیغاتی الف

کتابخانه logging یکی از ابزارهای استاندارد و قدرتمند پایتون برای ثبت لاگ و مدیریت پیام‌های گزارش‌دهی (logs) است. این ماژول به شما اجازه می‌دهد خطاها، پیام‌های دیباگ و اطلاعات اجرایی را به صورت ساخت‌یافته و قابل کنترل ذخیره یا نمایش دهید. یادگیری logging برای پروژه‌های واقعی، سرویس‌های تحت وب و برنامه‌های بزرگ ضروری است.

چرا از logging استفاده کنیم؟

  • جایگزین چاپ مستقیم با print برای نگهداری تاریخچه عملیات.
  • قابلیت تنظیم سطوح (levels) و فیلتر کردن پیام‌ها.
  • ارسال لاگ‌ها به مقصدهای مختلف: فایل، کنسول، سرورهای متمرکز یا پایگاه‌داده.
  • فرمت‌بندی قابل تنظیم و پشتیبانی از ساختاردهی اطلاعات (structured logging).

سطوح لاگ در logging

پنج سطح اصلی و دو سطح کمکی وجود دارد که معمولاً استفاده می‌شوند. در جدول زیر سطوح و معنی مختصر هر کدام آمده است:

سطحمقدار عددیکاربرد
CRITICAL50خطاهای بحرانی که نیاز به توقف یا توجه فوری دارند
ERROR40خطاهایی که بخش‌هایی از برنامه را خراب می‌کنند
WARNING30هشدارها و شرایط غیرعادی
INFO20اطلاعات کلی دربارهٔ جریان برنامه
DEBUG10اطلاعات دقیق برای دیباگ

مثال پایه‌ای: راه‌اندازی ساده

import logging

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

logger.info("شروع برنامه")
logger.debug("این پیام در سطح DEBUG است")
try:
    1 / 0
except ZeroDivisionError:
    logger.exception("خطای تقسیم بر صفر")

این کد یک پیکربندی پایه با basicConfig انجام می‌دهد، یک logger می‌سازد و پیام‌ها را با فرمت زمان، نام logger، سطح و متن پیام چاپ می‌کند. توجه کنید که logger.debug چاپ نمی‌شود چون سطح کلی INFO تنظیم شده است. logger.exception هنگام ثبت خطا، trace و اطلاعات استثنا را نیز نمایش می‌دهد.

استفاده از Handler و Formatter

یکی از مزایای logging جدا کردن منبع پیام‌ها (logger)، مقصد پیام‌ها (handler) و فرمت نمایش (formatter) است. این جداشدگی به شما امکان ارسال هم‌زمان لاگ‌ها به فایل، کنسول یا سرویس‌های بیرونی را می‌دهد.

import logging
from logging import FileHandler, StreamHandler

logger = logging.getLogger('myapp')
logger.setLevel(logging.DEBUG)

console_handler = StreamHandler()
console_handler.setLevel(logging.INFO)
file_handler = FileHandler('app.log')
file_handler.setLevel(logging.DEBUG)

fmt = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s')
console_handler.setFormatter(fmt)
file_handler.setFormatter(fmt)

logger.addHandler(console_handler)
logger.addHandler(file_handler)

logger.debug("این پیام در فایل ذخیره می‌شود و کنسول نمایش داده نمی‌شود")
logger.info("این پیام در هر دو مقصد نمایش می‌یابد")

در این مثال، یک logger با نام myapp ایجاد شده و دو handler به آن اضافه شده است: یکی برای کنسول (سطح INFO) و دیگری برای فایل (سطح DEBUG). بنابراین پیام‌های DEBUG در فایل ذخیره می‌شوند اما در کنسول نمایش داده نخواهند شد.

مدیریت اندازه فایل: RotatingFileHandler

from logging.handlers import RotatingFileHandler

rhandler = RotatingFileHandler('app_rot.log', maxBytes=1024*1024, backupCount=3)
rhandler.setFormatter(fmt)
rhandler.setLevel(logging.INFO)
logger.addHandler(rhandler)

RotatingFileHandler باعث می‌شود فایل لاگ بعد از رسیدن به اندازه مشخص (اینجا 1 مگابایت) چرخش (rotate) کند و نسخه‌های پشتیبان تا تعداد مشخصی نگهداری شوند. این روش برای جلوگیری از رشد نامحدود فایل لاگ مناسب است.

بهترین شیوه‌ها و نکات حرفه‌ای

  • از print در کدهای تولیدی استفاده نکنید؛ logging را تنظیم و استفاده کنید.
  • سطوح مناسب را انتخاب کنید: از DEBUG برای توسعه و از INFO/WARNING/ERROR برای محیط تولید.
  • اطلاعات حساس (پسورد، توکن‌ها) را هرگز لاگ نکنید یا آن‌ها را ماسک کنید.
  • برای اپلیکیشن‌های توزیع‌شده، از لاگ‌های ساخت‌یافته (JSON) و متمرکز مثل ELK یا Loki استفاده کنید.
  • به جای basicConfig در اپ‌های بزرگ از dictConfig یا fileConfig استفاده کنید تا پیکربندی قابل نگهداری و مدیریت باشد.
  • از loggerهای نام‌گذاری‌شده (getLogger(__name__)) استفاده کنید تا بتوانید سطوح را به صورت ماژولی کنترل کنید.
  • برای کار با چند فرآیند یا چند رشته از handlers/thread/process-safe مطمئن شوید (مثل QueueHandler).

مثال: ارسال JSON به یک فایل برای لاگ متمرکز

import logging
import json

class JsonFormatter(logging.Formatter):
    def format(self, record):
        data = {
            "time": self.formatTime(record),
            "level": record.levelname,
            "name": record.name,
            "message": record.getMessage(),
        }
        return json.dumps(data)

jf = JsonFormatter()
jh = FileHandler('app.json.log')
jh.setFormatter(jf)
logger.addHandler(jh)
logger.info("کاربر لاگ شد", extra={"user_id": 123})

در این مثال یک Formatter سفارشی برای تولید خروجی JSON ساخته‌ایم. با این روش می‌توان لاگ‌ها را به سرویس‌های جستجو/مانیتورینگ فرستاد یا به‌صورت ساخت‌یافته ذخیره کرد. پارامتر extra امکان افزودن فیلدهای دلخواه را فراهم می‌کند.

خلاصه و جمع‌بندی

ماژول logging ابزار انعطاف‌پذیر و استاندارد پایتون برای ثبت لاگ است. با فهمیدن loggerها، handlerها، formatterها و سطوح، می‌توانید سیستم گزارش‌دهی قابل اطمینان، امن و مقیاس‌پذیر بسازید. در پروژه‌های بزرگ از پیکربندی‌های پیشرفته، لاگ‌های ساخت‌یافته و سرویس‌های متمرکز استفاده کنید و از ثبت اطلاعات حساس خودداری نمایید.

در صورت نیاز می‌توان مثال‌های بیشتری مانند dictConfig، QueueHandler/QueueListener برای پردازش ناهمزمان یا integration با Sentry و ELK را نیز ارائه داد.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: