کتابخانه logging در پایتون
کتابخانه logging یکی از ابزارهای استاندارد و قدرتمند پایتون برای ثبت لاگ و مدیریت پیامهای گزارشدهی (logs) است. این ماژول به شما اجازه میدهد خطاها، پیامهای دیباگ و اطلاعات اجرایی را به صورت ساختیافته و قابل کنترل ذخیره یا نمایش دهید. یادگیری logging برای پروژههای واقعی، سرویسهای تحت وب و برنامههای بزرگ ضروری است.
چرا از logging استفاده کنیم؟
- جایگزین چاپ مستقیم با print برای نگهداری تاریخچه عملیات.
- قابلیت تنظیم سطوح (levels) و فیلتر کردن پیامها.
- ارسال لاگها به مقصدهای مختلف: فایل، کنسول، سرورهای متمرکز یا پایگاهداده.
- فرمتبندی قابل تنظیم و پشتیبانی از ساختاردهی اطلاعات (structured logging).
سطوح لاگ در logging
پنج سطح اصلی و دو سطح کمکی وجود دارد که معمولاً استفاده میشوند. در جدول زیر سطوح و معنی مختصر هر کدام آمده است:
| سطح | مقدار عددی | کاربرد |
|---|---|---|
| CRITICAL | 50 | خطاهای بحرانی که نیاز به توقف یا توجه فوری دارند |
| ERROR | 40 | خطاهایی که بخشهایی از برنامه را خراب میکنند |
| WARNING | 30 | هشدارها و شرایط غیرعادی |
| INFO | 20 | اطلاعات کلی دربارهٔ جریان برنامه |
| DEBUG | 10 | اطلاعات دقیق برای دیباگ |
مثال پایهای: راهاندازی ساده
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 را نیز ارائه داد.
آیا این مطلب برای شما مفید بود ؟




