📝 لاگنویسی (Logging) در پایتون
لاگنویسی یکی از مهمترین مهارتها در توسعه نرمافزار است که به شما امکان میدهد رویدادها، خطاها و اطلاعات برنامه را ثبت کنید.
ماژول logging در پایتون یک سیستم استاندارد و قدرتمند برای ثبت وقایع ارائه میدهد که به شما کمک میکند برنامه خود را دیباگ کنید و عملکرد آن را مانیتور کنید.
🔹 تنظیمات پایه و سطوح لاگ
import logging
# تنظیمات پایه
logging.basicConfig(
level=logging.DEBUG, # سطح لاگ
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# تست سطوح مختلف
logging.debug("This is a DEBUG message")
logging.info("This is an INFO message")
logging.warning("This is a WARNING message")
logging.error("This is an ERROR message")
logging.critical("This is a CRITICAL message")
🔹 سطوح لاگ (Log Levels)
🔹 فرمتبندی لاگها
import logging
# فرمتهای مختلف
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)-8s - %(name)-15s - %(message)s',
datefmt='%H:%M:%S'
)
logger = logging.getLogger('my_app')
logger.info("Application started")
logger.warning("Low memory warning")
# فرمت با کدهای رنگی (برای ترمینال)
# میتوانید از کتابخانههای colorlog استفاده کنید
🔹 نوشتن لاگ در فایل
import logging
# تنظیم لاگ در فایل
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler("app.log", encoding='utf-8'), # ذخیره در فایل
logging.StreamHandler() # نمایش در کنسول
]
)
logger = logging.getLogger(__name__)
logger.info("This message goes to both file and console")
logger.error("Error message with timestamp")
# نوشتن در فایل جداگانه برای خطاها
error_handler = logging.FileHandler("errors.log")
error_handler.setLevel(logging.ERROR)
error_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
logger.addHandler(error_handler)
logger.error("This error goes to errors.log")
🔹 Loggerهای مختلف
import logging
# تنظیمات پایه
logging.basicConfig(level=logging.DEBUG)
# Logger برای ماژولهای مختلف
logger1 = logging.getLogger('module1')
logger2 = logging.getLogger('module2')
logger1.info("This is module1 message")
logger2.warning("This is module2 warning")
# تنظیم سطح متفاوت برای هر logger
logger1.setLevel(logging.WARNING)
logger2.setLevel(logging.DEBUG)
logger1.debug("This won't show (level WARNING)")
logger2.debug("This will show (level DEBUG)")
# استفاده از logger با سلسلهمراتب
parent = logging.getLogger('app')
child = logging.getLogger('app.module')
parent.info("Parent logger")
child.info("Child logger (inherits parent settings)")
🔹 لاگکردن استثناها (Exceptions)
import logging
logging.basicConfig(level=logging.ERROR)
logger = logging.getLogger(__name__)
try:
result = 10 / 0
except ZeroDivisionError as e:
# لاگ کامل استثنا با traceback
logger.error("Division by zero occurred", exc_info=True)
# یا
logger.exception("Division by zero occurred") # خودکار exc_info=True
try:
int("abc")
except ValueError:
# لاگ بدون traceback
logger.error("Invalid conversion", exc_info=False)
🔹 پیکربندی پیشرفته (dictConfig)
import logging
import logging.config
# پیکربندی با دیکشنری
LOGGING_CONFIG = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
},
'detailed': {
'format': '%(asctime)s - %(name)s - %(levelname)s - %(module)s - %(message)s'
}
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'level': 'DEBUG',
'formatter': 'standard'
},
'file': {
'class': 'logging.FileHandler',
'filename': 'app.log',
'level': 'INFO',
'formatter': 'detailed',
'encoding': 'utf-8'
}
},
'loggers': {
'app': {
'level': 'DEBUG',
'handlers': ['console', 'file'],
'propagate': False
},
'app.module1': {
'level': 'INFO',
'handlers': ['console'],
'propagate': False
}
},
'root': {
'level': 'WARNING',
'handlers': ['console']
}
}
logging.config.dictConfig(LOGGING_CONFIG)
logger = logging.getLogger('app')
logger.debug("Debug message from app")
logger.info("Info message from app")
module1_logger = logging.getLogger('app.module1')
module1_logger.info("Info from module1")
module1_logger.debug("Debug from module1 (won't show)")
🔹 چرخش لاگ (RotatingFileHandler)
import logging
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
# RotatingFileHandler: چرخش بر اساس حجم
rotating_handler = RotatingFileHandler(
"app.log",
maxBytes=1000, # حداکثر حجم هر فایل (بایت)
backupCount=3 # تعداد فایلهای پشتیبان
)
rotating_handler.setLevel(logging.DEBUG)
rotating_handler.setFormatter(logging.Formatter('%(asctime)s - %(message)s'))
logger = logging.getLogger('rotating')
logger.addHandler(rotating_handler)
# TimedRotatingFileHandler: چرخش بر اساس زمان
timed_handler = TimedRotatingFileHandler(
"app_timed.log",
when="midnight", # هر روز نیمهشب
backupCount=7 # ۷ روز پشتیبان
)
timed_handler.setLevel(logging.INFO)
timed_handler.setFormatter(logging.Formatter('%(asctime)s - %(message)s'))
logger.addHandler(timed_handler)
logger.info("This log will rotate daily")
🔹 مثال جامع: سیستم لاگگیری برنامه
import logging
import logging.config
import datetime
# پیکربندی لاگ
LOGGING_CONFIG = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'simple': {
'format': '%(asctime)s - %(levelname)-8s - %(message)s'
},
'detailed': {
'format': '%(asctime)s - %(name)s - %(levelname)-8s - %(module)s:%(lineno)d - %(message)s'
}
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'level': 'DEBUG',
'formatter': 'simple'
},
'app_file': {
'class': 'logging.handlers.RotatingFileHandler',
'filename': 'app.log',
'maxBytes': 1024*1024, # 1 MB
'backupCount': 5,
'level': 'INFO',
'formatter': 'detailed',
'encoding': 'utf-8'
},
'error_file': {
'class': 'logging.handlers.RotatingFileHandler',
'filename': 'errors.log',
'maxBytes': 1024*1024,
'backupCount': 3,
'level': 'ERROR',
'formatter': 'detailed',
'encoding': 'utf-8'
}
},
'loggers': {
'app': {
'level': 'DEBUG',
'handlers': ['console', 'app_file'],
'propagate': False
},
'app.errors': {
'level': 'ERROR',
'handlers': ['error_file'],
'propagate': False
}
},
'root': {
'level': 'WARNING',
'handlers': ['console']
}
}
logging.config.dictConfig(LOGGING_CONFIG)
class AppLogger:
"""کلاس مدیریت لاگهای برنامه"""
def __init__(self, name):
self.logger = logging.getLogger(f'app.{name}')
self.error_logger = logging.getLogger('app.errors')
def debug(self, message):
self.logger.debug(message)
def info(self, message):
self.logger.info(message)
def warning(self, message):
self.logger.warning(message)
def error(self, message, exc_info=False):
self.logger.error(message, exc_info=exc_info)
self.error_logger.error(message, exc_info=exc_info)
def critical(self, message):
self.logger.critical(message)
self.error_logger.critical(message)
# استفاده
logger = AppLogger('user_service')
logger.info("User service started")
logger.debug("Loading configuration...")
logger.warning("Database connection slow")
try:
# شبیهسازی خطا
user_data = {"id": 1, "name": "Saba"}
if not user_data.get("email"):
raise ValueError("Email is required")
except ValueError as e:
logger.error(f"User validation error: {e}", exc_info=True)
logger.info("User service shutdown")
📌 نکات کلیدی
- ✅ ماژول
loggingیک سیستم استاندارد برای ثبت وقایع است. - ✅ سطوح لاگ:
DEBUG<INFO<WARNING<ERROR<CRITICAL - ✅ با
basicConfig()میتوانید تنظیمات پایه را انجام دهید. - ✅ با
FileHandlerلاگها را در فایل ذخیره کنید. - ✅ با
RotatingFileHandlerوTimedRotatingFileHandlerچرخش فایلها را مدیریت کنید. - ✅ با
exc_info=Trueیاlogger.exception()traceback را لاگ کنید. - ✅ با
dictConfigمیتوانید پیکربندی پیشرفته انجام دهید. - ✅ از loggerهای جداگانه برای ماژولهای مختلف استفاده کنید.
- ✅ لاگنویسی به دیباگ و مانیتورینگ برنامه کمک میکند.