آنچه در این مقاله میخوانید [پنهانسازی]
اگر دنبال راهی ساده و حرفه ای برای ثبت لاگ در برنامه های پایتونی هستید، کتابخانه Loguru گزینه ای سریع، قابل اعتماد و بسیار منعطف است. این ابزار دردسرهای پیکربندی طولانی و پیچیدگی های ماژول logging استاندارد را کم می کند و به شما اجازه می دهد در چند خط، خروجی های خوانا، ساخت یافته و قابل جستجو بسازید. در این راهنما با اصول، ترفندها و بهترین شیوه های کار با آن آشنا می شوید تا از همان امروز کیفیت عیب یابی و مشاهده رفتار سیستم را بهبود دهید.
معرفی و شروع سریع
در پروژه های کوچک یا بزرگ، لاگ نویسی باید قابل اعتماد، شفاف و قابل نگهداری باشد. Loguru با تمرکز بر تجربه توسعه دهنده، پیکربندی را ساده کرده و امکاناتی مثل قالب دهی پیشرفته، چرخش فایل ها، نگهداری زمان دار و گزارش خطای غنی را بدون نوشتن کد اضافی ارائه می دهد.
برای نصب، کافی است پکیج را با pip اضافه کنید. سپس با چند خط کد، خروجی به کنسول و فایل داشته باشید و سطح های مختلف لاگ را کنترل کنید.
pip install loguru
from loguru import logger
logger.info("برنامه شروع شد")
logger.debug("مقدار متغیر x برابر است با {}", 42)
logger.warning("هشدار: مقدار حافظه در حال افزایش است")
logger.error("خطا: اتصال به پایگاه داده برقرار نشد")
logger.success("عملیات با موفقیت انجام شد")
برای ذخیره در فایل به همراه چرخش خودکار و نگهداری محدود، تنها یک فراخوانی نیاز دارید. دیگر نیازی به کلاس های متعدد هندلر نیست و پارامترها کاملا سرراست هستند.
from loguru import logger
logger.add(
"logs/app.log",
rotation="10 MB", # بعد از 10 مگابایت فایل جدید بساز
retention="7 days", # لاگ ها را 7 روز نگه دار
compression="zip", # فایل های قدیمی را فشرده کن
encoding="utf-8"
)
logger.info("لاگ نویسی فایل به درستی پیکربندی شد")
در برنامه های چندپردازه یا چندریسمانی، برای جلوگیری از قفل شدن و افزایش کارایی، می توانید ارسال غیرهمزمان را فعال کنید. این کار صف امنی برای انتقال پیام ها به سینک ها ایجاد می کند.
logger.add("logs/async.log", enqueue=True, rotation="1 day")
پیکربندی حرفه ای و ویژگی ها
کتابخانه Loguru مجموعه ای از امکانات عملی برای سناریوهای دنیای واقعی دارد. از چندین سینک همزمان گرفته تا فرمت های غنی و گزارش خطاهای قابل پیگیری. در ادامه مهم ترین قابلیت ها و نحوه استفاده از آنها را مرور می کنیم.
- سینک های متعدد: کنسول، فایل، استریم دلخواه، و حتی توابع سفارشی
- سطح ها و فیلترها: کنترل دقیق اینکه چه چیزی کجا ثبت شود
- قالب دهی پیشرفته: زمان، سطح، نام ماژول، خط و پیام با الگوی دلخواه
- JSON نویسی: خروجی ساخت یافته برای مصرف توسط ELK، Loki یا Splunk
- چرخش و نگهداری: کنترل اندازه، زمان و تعداد فایل های لاگ
- گزارش خطای غنی: backtrace و diagnose برای تشخیص سریع تر
- زمینه های اضافی: افزودن context مانند شناسه درخواست یا کاربر
- ارسال غیرهمزمان: بهبود عملکرد در بارهای سنگین
برای تعریف چند سینک با سطح و فرمت متفاوت، می توانید logger.add را چند بار فراخوانی کنید. در نمونه زیر، خطاها به فایل جداگانه می روند و خروجی کنسول رنگی است.
from loguru import logger
# کنسول با فرمت خوانا و رنگی
logger.add(
sys.stderr,
level="INFO",
colorize=True,
format="{time:YYYY-MM-DD HH:mm:ss} | <level>{level:<8}</level> | "
"{name}:{function}:{line} - <level>{message}</level>"
)
# فایل ویژه خطاها
logger.add(
"logs/errors.log",
level="ERROR",
rotation="5 MB",
retention="14 days",
backtrace=True,
diagnose=True
)
برای خروجی ساخت یافته، serialize را فعال کنید. این کار لاگ ها را به صورت JSON ثبت می کند و برای انتقال به ابزارهای مشاهده متمرکز ایده آل است.
logger.add("logs/app.json", serialize=True, rotation="1 day")
logger.bind(service="billing", region="teh").info("پرداخت رسید")
افزودن context باعث می شود همه پیام های بعدی آن بخش، اطلاعات اضافی مورد نیاز را همراه داشته باشند. این موضوع در سیستم های توزیع شده برای ردگیری درخواست ها حیاتی است.
request_logger = logger.bind(request_id="abc-123", user_id=77)
request_logger.info("دریافت درخواست جدید")
برای ثبت استثناها بدون try…except های تکراری، از دکوریتور catch یا context manager استفاده کنید. backtrace و diagnose کمک می کنند ریشه خطا با جزئیات کافی نمایش داده شود.
from loguru import logger
@logger.catch
def run_job():
1 / 0 # خطای عمدی
run_job()
اگر می خواهید پیام های یک ماژول یا مسیر خاص را جدا نگه دارید، از فیلتر سفارشی استفاده کنید. فیلتر می تواند نام ماژول، الگو یا تابع باشد.
def only_api_records(record):
return "api" in record["name"]
logger.add("logs/api.log", filter=only_api_records)
ادغام در پروژه و بهترین شیوه ها
بسیاری از پروژه ها از قبل با logging استاندارد یا چاپ ساده کار می کنند. برای مهاجرت تدریجی، می توانید Loguru را به عنوان لایه مرکزی لاگ نویسی قرار دهید و خروجی های دیگر را به آن هدایت کنید. این کار بدون بازنویسی بزرگ انجام می شود و به سرعت مزایای عملی آن را می بینید. ادغام کتابخانه Loguru در چند گام ساده شدنی است.
- یک ماژول پیکربندی مرکزی بسازید و همه تنظیمات logger.add را آنجا نگه دارید.
- تمام print ها را به logger.info یا سطح مناسب تبدیل کنید.
- لاگ های logging استاندارد و فریم ورک ها را به Loguru هدایت کنید.
- سطح و سینک ها را بر اساس محیط توسعه، تست و تولید تغییر دهید.
- با تست های واحد و یکپارچه، وجود پیام های ضروری و فرمت صحیح را بررسی کنید.
برای جذب خروجی logging استاندارد، یک هندلر ساده بنویسید تا رکوردها را به Loguru بفرستد. با این روش نیازی به تغییر همه import ها ندارید.
import logging
from loguru import logger
class InterceptHandler(logging.Handler):
def emit(self, record):
try:
level = logger.level(record.levelname).name
except Exception:
level = "INFO"
logger.opt(depth=6, exception=record.exc_info).log(level, record.getMessage())
# جایگزینی هندلرهای logging با InterceptHandler
logging.basicConfig(handlers=[InterceptHandler()], level=0)
logging.getLogger().handlers = [InterceptHandler()]
# از اینجا به بعد، logging نیز توسط Loguru مدیریت می شود
logging.getLogger("urllib3").setLevel(logging.WARNING)
برای کنترل سطح ها بر اساس محیط، از متغیرهای محیطی کمک بگیرید تا در تولید تنها لاگ های مهم ذخیره شوند و در توسعه جزئیات بیشتری ببینید.
import os
level = os.getenv("LOG_LEVEL", "INFO")
logger.remove()
logger.add(sys.stderr, level=level, colorize=True)
logger.add("logs/app.log", level=level, rotation="10 MB", retention="7 days")
در برنامه های وب، پیوست کردن شناسه درخواست به همه پیام ها بسیار مفید است. با bind می توانید این داده ها را به صورت خودکار اضافه کنید.
def handle_request(req):
req_logger = logger.bind(request_id=req.id, path=req.path)
req_logger.info("شروع پردازش")
# ...
req_logger.info("پایان پردازش")
اگر می خواهید تفاوت های کلیدی بین رویکرد کلاسیک و Loguru را یکجا ببینید، جدول زیر شمای کلی ارائه می کند.
| logging استاندارد | Loguru |
|---|---|
| پیکربندی پیچیده با دیکشنری یا کد طولانی | راه اندازی یک خطی با logger.add |
| نیاز به کلاس های Handler و Formatter سفارشی | سینک ها و فرمت ساده به صورت پارامتر |
| چرخش فایل با RotatingFileHandler و تنظیمات پراکنده | rotation و retention یکپارچه در همان افزودن سینک |
| جزئیات استثنا محدود به traceback عادی | backtrace و diagnose برای گزارش خطای غنی |
برای بیشترین اثربخشی، چند نکته عملی را رعایت کنید. این نکات به بهبود کارایی، خوانایی و امنیت کمک می کنند و نگهداری تیمی را ساده تر می سازند.
- نام گذاری فایل ها و مسیر لاگ را بر اساس سرویس و محیط استاندارد کنید.
- برای تولید از serialize=True استفاده کنید تا تحلیل مرکزی آسان شود.
- اطلاعات حساس مثل توکن ها را قبل از ثبت، ماسک کنید.
- سطح ها را جدی بگیرید: DEBUG برای توسعه، INFO برای روند عادی، WARNING و بالاتر برای رخدادهای مهم.
- برای پردازش همزمان یا چندپردازه، enqueue=True را فعال کنید.
- rotation و retention را متناسب با فضای دیسک و الزامات قانونی تنظیم کنید.
- با bind شناسه های مهم مانند request_id، session_id یا user_id را به لاگ بیفزایید.
- برای نویز کمتر، لاگ کتابخانه های پر سر و صدا را فیلتر یا سطح آنها را کاهش دهید.
جمع بندی
لاگ نویسی زمانی ارزشمند است که خوانا، قابل جستجو و قابل اتکا باشد. با استفاده از یک نقطه ورود ساده، فرمت های شفاف و امکاناتی مانند چرخش فایل، نگهداری زمان دار، گزارش خطاهای غنی و خروجی JSON، می توانید کیفیت نظارت و عیب یابی را در هر مقیاسی ارتقا دهید. پیشنهاد می شود پیکربندی مرکزی بسازید، سطح ها را بر اساس محیط تنظیم کنید و با افزودن context های معنادار، مسیر هر درخواست را از ابتدا تا انتها دنبال کنید. در نهایت، با چند خط کد و تصمیم های دقیق، زیرساخت لاگ پروژه شما به ابزاری قابل اعتماد برای نگهداری و رشد تبدیل می شود.






