مدیریت هشدارها (Warnings) بخش مهمی از توسعه نرمافزار حرفهای است. برخلاف خطاها (Errors) که برنامه را متوقف میکنند، هشدارها پیامی مبنی بر اینکه "اتفاقی غیرمنتظره رخ داده یا کدی در آینده منسوخ میشود" به کاربر میدهند، اما اجازه میدهند برنامه به کار خود ادامه دهد.
در این مقاله، از نحوه تولید یک هشدار ساده تا مدیریت پیشرفتهی آنها در پروژههای بزرگ را بررسی میکنیم.
سطح مقدماتی (Beginner Level)
در این بخش با ماژول داخلی warnings آشنا میشویم، یاد میگیریم چگونه هشدار تولید کنیم و انواع دستهبندیهای استاندارد آن را بشناسیم.
۱. تولید اولین هشدار (Using warn)
سادهترین روش برای نمایش یک هشدار به کاربر، استفاده از تابع warn() است. این تابع شبیه به print عمل نمیکند، بلکه خروجی را به stderr میفرستد و معمولاً شامل نام فایل و شماره خط است.
مثال ۱: هشدار ساده
در این مثال یک هشدار عمومی تولید میکنیم. از آنجا که این کد کامل است و اجرا میشود، از بلوک python-run استفاده میکنیم.
مثال ۲: استفاده از دستهبندیها (Categories)
پایتون دستهبندیهای مختلفی برای هشدارها دارد (مثل DeprecationWarning برای کدهای منسوخ شده). تعیین نوع هشدار به برنامهنویسان دیگر کمک میکند تا ماهیت مشکل را بهتر درک کنند.
۲. فیلتر کردن هشدارها (Simple Filtering)
گاهی اوقات میخواهید هشدارها را نادیده بگیرید یا رفتار آنها را تغییر دهید (مثلاً فقط یک بار نمایش داده شوند). برای این کار از simplefilter استفاده میکنیم.
آرگومانهای رایج simplefilter:
"ignore": هیچ هشداری چاپ نشود."always": همیشه هشدار چاپ شود (حتی اگر تکراری باشد)."once": هر هشدار فقط یک بار در طول اجرای برنامه چاپ شود.
مثال ۱: نادیده گرفتن تمام هشدارها
این کد هیچ هشداری را در خروجی نشان نمیدهد.
مثال ۲: جلوگیری از تکرار (Once)
اگر یک هشدار داخل حلقه باشد، ممکن است هزاران بار چاپ شود. با once جلوی این کار را میگیریم.
سطح پیشرفته (Professional Level)
در پروژههای بزرگ و کتابخانهها، مدیریت هشدارها پیچیدهتر میشود. در این بخش به سراغ catch_warnings، تبدیل هشدار به خطا برای تستهای واحد (Unit Tests) و ساخت کلاسهای سفارشی میرویم.
۱. مدیریت موقت با Context Manager
استفاده از تنظیمات سراسری (Global) برای فیلتر هشدارها میتواند روی کل برنامه تأثیر بگذارد. راه حرفهایتر، استفاده از warnings.catch_warnings() است که تغییرات را فقط در یک بلوک خاص اعمال میکند.
مثال ۱: ضبط هشدارها (Recording Warnings)
گاهی نیاز دارید بررسی کنید آیا تابعی هشدار داده است یا خیر (بدون اینکه آن را در کنسول چاپ کنید).
مثال ۲: نادیده گرفتن هشدار فقط برای یک تابع خاص
فرض کنید از یک کتابخانه خارجی استفاده میکنید که هشدارهای آزاردهنده میدهد، اما نمیخواهید هشدارهای کد خودتان را غیرفعال کنید.
# Static Snippet: نمایش ساختار کلی بدون اجرا
import warnings
def specific_suppression():
# فقط هشدارهای داخل این بلوک نادیده گرفته میشوند
with warnings.catch_warnings():
warnings.simplefilter("ignore")
# external_library.noisy_function()
# هشدارهای اینجا همچنان فعال هستند
warnings.warn("This will still be shown")
۲. تبدیل هشدار به خطا (Warnings as Errors)
در محیطهای CI/CD (توسعه مداوم)، بسیار مهم است که هشدارهایی مثل DeprecationWarning نادیده گرفته نشوند تا کد در آینده خراب نشود. میتوانیم پایتون را مجبور کنیم که با هشدارها مثل Exception برخورد کند.
مثال ۱: متوقف کردن برنامه با هشدار
در این مثال، برنامه با بروز هشدار متوقف میشود (Crashing).
۳. هشدارهای سفارشی (Custom Warnings)
برای توسعهدهندگان کتابخانه، استفاده از UserWarning عمومی کافی نیست. شما باید کلاس هشدار مخصوص خود را بسازید که از کلاس پایه Warning ارثبری کند.
مثال ۱: تعریف کلاس (Static)
این صرفاً تعریف کلاس است و به تنهایی اجرا نمیشود.
# تعریف یک کلاس هشدار سفارشی
class PerformanceWarning(Warning):
"""هشداری برای عملیاتهایی که زمان زیادی میبرند."""
pass
مثال ۲: استفاده از هشدار سفارشی در اسکریپت
اینجا کلاس را تعریف کرده و استفاده میکنیم. همچنین با استفاده از filterwarnings فقط همین نوع هشدار خاص را مدیریت میکنیم.
۴. فیلتر کردن پیشرفته با RegEx
تابع filterwarnings بسیار قدرتمند است. شما میتوانید بر اساس متن پیام هشدار، ماژول صادر کننده و شماره خط فیلتر کنید.
