|
236 | 236 | در زبانبرنامهنویسی پایتون پیشنهاد میشود که اگر هدف از ایجاد Exception نمایش یک خطا باشد، در انتهای نام کلاس از واژه Error استفاده گردد. |
237 | 237 |
|
238 | 238 |
|
239 | | -Context Manager و ``with`` |
| 239 | +ماژول warnings |
240 | 240 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
241 | 241 |
|
| 242 | +تا این لحظه با مفهوم Exception آشنا شدهایم. میدانیم که بروز Exception در واقع اعلام یک خطا یا یک رویداد مهم در برنامه میباشد که میبایست حتما handle شود، در غیر این صورت برنامه قادر به انجام دستورات نخواهد بود. |
242 | 243 |
|
243 | | -ماژول warnings |
244 | | -~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 244 | +اما گاهی اعلام یک رویداد آنقدر مهم نیست که بخواهد روند اجرای برنامه تهدید کند. بلکه صرفا یک هشدار برای توجه بیشتر یا اصلاح رفتار برای نسخههای بعدی خواهد بود که **بیشتر کاربرد آن برای توسعهدهندگان برنامه میباشد تا کاربرانی که به نوعی مصرفکنندگان آن برنامه محسوب میشوند**. در زبان برنامهنویسی پایتون، ماژول ``warnings`` [`اسناد پایتون <https://docs.python.org/3/library/warnings.html>`__] را برای استفاده در چنین زمانهایی فراهم آورده شده است [`PEP 230 <https://www.python.org/dev/peps/pep-0230>`__]. |
| 245 | + |
| 246 | + |
| 247 | +پیش از مراجعه به این ماژول از کتابخانه استاندارد زبان برنامهنویسی پایتون لازم است نگاهی دوباره به انتهای فهرست سلسلهمراتب وراثت Exceptionها که در درس پیش آن را بررسی کردیم بیاندازیم، در انتهای این فهرست کلاسهایی با پسوند Warning قراردارند [`Exception hierarchy <https://docs.python.org/3/library/exceptions.html#exception-hierarchy>`__]: |
| 248 | + |
| 249 | + |
| 250 | +.. image:: /_static/l24-python-exception-hierarchy-warnings.png |
| 251 | + :align: center |
| 252 | + :alt: Exception Hierarchy در پایتون به همراه warnings |
| 253 | + |
| 254 | +همانطور که مشاهده میشود، تمام این کلاسها از کلاسی با نام ``Warning`` ارثبری دارند که خود این کلاس نیز از کلاس ``Exception`` ارثبری دارد. |
| 255 | + |
| 256 | +اینها Warning هستند، Exceptionهایی که هدف از توسعه آنها اعلام یک هشدار میباشد و نه اعتراضی که تنبیه آن توقف برنامه باشد. با این حال به نمونه کد زیر توجه نمایید: |
| 257 | + |
| 258 | +.. code-block:: python |
| 259 | + :linenos: |
| 260 | +
|
| 261 | + def sum_int(a, b): |
| 262 | + raise DeprecationWarning('"sum_int" will be removed in version 2.0') |
| 263 | + sum = a + b |
| 264 | + print(sum) |
| 265 | +
|
| 266 | +
|
| 267 | + sum_int(6, 5) |
| 268 | + print('Done.') |
| 269 | +
|
| 270 | +:: |
| 271 | + |
| 272 | + Traceback (most recent call last): |
| 273 | + File "sample.py", line 7, in <module> |
| 274 | + sum_int(6, 5) |
| 275 | + File "sample.py", line 2, in sum_int |
| 276 | + raise DeprecationWarning('"sum_int" will be removed in version 2.0') |
| 277 | + DeprecationWarning: "sum_int" will be removed in version 2.0 |
| 278 | + |
| 279 | +ساختار سلسلهمراتب به ما گفته بود که Warningها در اصل Exception هستند و زمانی که یک Exception به اصطلاح raise شود، حتما میبایست یک handler برای آن پیشبینی شده باشد. در واقع اگر برای بروز یک Warning از دستور ``raise`` استفاده شود، دستور ``raise`` همان کاری را با Warning انجام میدهد که با هر نوع Exception دیگری انجام خواهد داد. |
| 280 | + |
| 281 | + |
| 282 | +تابع ``warnings.warn`` |
| 283 | +--------------------------- |
| 284 | + |
| 285 | + |
| 286 | +اگر بخواهیم بروز یک Exception به صورتی هشدارگونه باشد، میبایست به سراغ ماژول ``warnings`` برویم. اکنون اگر نمونه کد قبل را با کمک این ماژول بازنویسی نماییم، نتیجه زیر حاصل میگردد: |
| 287 | + |
| 288 | +.. code-block:: python |
| 289 | + :linenos: |
| 290 | +
|
| 291 | + import warnings |
| 292 | +
|
| 293 | + def sum_int(a, b): |
| 294 | + warnings.warn('"sum_int" will be removed in version 2.0', DeprecationWarning) |
| 295 | + sum = a + b |
| 296 | + print(sum) |
| 297 | +
|
| 298 | +
|
| 299 | + sum_int(6, 5) |
| 300 | + print('Done.') |
| 301 | +
|
| 302 | +:: |
| 303 | + |
| 304 | + sample.py:4: DeprecationWarning: "sum_int" will be removed in version 2.0 |
| 305 | + warnings.warn('"sum_int" will be removed in version 2.0', DeprecationWarning) |
| 306 | + 11 |
| 307 | + Done. |
| 308 | + |
| 309 | +همانطور که مشاهده میشود تنها یک پیام هشدار در خروجی چاپ (print) میشود و دیگر خبری از Traceback نیست و برنامه بدون هیچ اخلالی باموفقیت تا خط پایان به اجرای خود ادامه داده است. |
| 310 | + |
| 311 | + |
| 312 | +برای اعلام یک هشدار از تابع ``warn`` در ماژول ``warnings`` استفاده میشود [`اسناد پایتون <https://docs.python.org/3/library/warnings.html#warnings.warn>`__] که تعریف آن به شکل زیر میباشد:: |
| 313 | + |
| 314 | + warn(message, category=None, stacklevel=1, source=None) |
| 315 | + |
| 316 | +بر اساس تعریف، این تابع یک پارامتر اجباری (``message``) و سه پارامتر اختیاری دارد. |
| 317 | + |
| 318 | +* **message**: میبایست یک شی ``str`` باشد و متن هشداری است که میخواهیم نمایش داده شود. |
| 319 | + |
| 320 | +* **category**: نوع Warning را مشخص میکند که میبایست **نام یک subclass از کلاس** ``Warning`` باشد. برای مشاهده انواع Warningهای از پیش آماده در پایتون میتوانید به `Warning Categories <https://docs.python.org/3/library/warnings.html#warning-categories>`__ مراجعه نمایید. ارسال آرگومان برای این پارامتر اختیاری است و در صورت عدم ارسال، نوع ``UserWarning`` به صورت پیشفرض در نظر گرفته خواهد شد. |
| 321 | + |
| 322 | +* **stacklevel**: اگر دقت کرده باشید متن هشدار شامل اطلاعاتی از محل بروز آن میباشد. این پارامتر یک عدد از نوع ``int`` و بزرگتر یا مساوی از ``1`` را دریافت و تعیین میکند که این اطلاعات مربوط به کدام سطح از فراخوانی کد و رسیدن به این هشدار باشد. به این صورت که: عدد ``1`` (مقدار پیشفرض) به محل دقیق بروز هشدار، عدد ``2`` به یک مرحله قبلتر از محل بروز هشدار و ... |
| 323 | + |
| 324 | + .. code-block:: python |
| 325 | + :linenos: |
| 326 | +
|
| 327 | +
|
| 328 | + import warnings |
| 329 | +
|
| 330 | + def sum_int(a, b): |
| 331 | + print('-' * 30, 'stacklevel=1') |
| 332 | + warnings.warn('"sum_int" will be removed in version 2.0', stacklevel=1) |
| 333 | + print('-' * 30, 'stacklevel=2') |
| 334 | + warnings.warn('"sum_int" will be removed in version 2.0', stacklevel=2) |
| 335 | + print('-' * 30, 'stacklevel=3') |
| 336 | + warnings.warn('"sum_int" will be removed in version 2.0', stacklevel=3) |
| 337 | + print('-' * 30, 'stacklevel=4') |
| 338 | + warnings.warn('"sum_int" will be removed in version 2.0', stacklevel=4) |
| 339 | + print('-' * 30, 'stacklevel=5') |
| 340 | + warnings.warn('"sum_int" will be removed in version 2.0', stacklevel=5) |
| 341 | + print('-' * 30) |
| 342 | + sum = a + b |
| 343 | + print(sum) |
| 344 | +
|
| 345 | +
|
| 346 | + def action(a, b): |
| 347 | + sum_int(6, 5) |
| 348 | +
|
| 349 | +
|
| 350 | + action(6, 5) |
| 351 | + print('Done.') |
| 352 | +
|
| 353 | + :: |
| 354 | + |
| 355 | + ------------------------------ stacklevel=1 |
| 356 | + sample.py:5: UserWarning: "sum_int" will be removed in version 2.0 |
| 357 | + warnings.warn('"sum_int" will be removed in version 2.0', stacklevel=1) |
| 358 | + ------------------------------ stacklevel=2 |
| 359 | + sample.py:20: UserWarning: "sum_int" will be removed in version 2.0 |
| 360 | + sum_int(6, 5) |
| 361 | + ------------------------------ stacklevel=3 |
| 362 | + sample.py:23: UserWarning: "sum_int" will be removed in version 2.0 |
| 363 | + action(6, 5) |
| 364 | + ------------------------------ stacklevel=4 |
| 365 | + sys:1: UserWarning: "sum_int" will be removed in version 2.0 |
| 366 | + ------------------------------ stacklevel=5 |
| 367 | + ------------------------------ |
| 368 | + 11 |
| 369 | + Done. |
| 370 | + |
| 371 | +Warnings Filter |
| 372 | +---------------------- |
| 373 | + |
| 374 | +حالتی را تصور کنید که برنامه شما پر از Warningهای متنوع میباشد. Warnings Filter امکانی است برای اینکه مشخص کنیم کدام نوع Warning نادیده گرفته شود یا کدام نوع نمایش داده شود یا کدام نوع همچون یک Exception واقعی رفتار کند. برای این منظور از از تابع ``simplefilter`` در ماژول ``warnings`` استفاده میشود [`اسناد پایتون <https://docs.python.org/3/library/warnings.html#warnings.simplefilter>`__] که تعریف آن به شکل زیر میباشد:: |
| 375 | + |
| 376 | + simplefilter(action, category=Warning, lineno=0, append=False) |
| 377 | + |
| 378 | +بر اساس تعریف، این تابع یک پارامتر اجباری (``action``) و سه پارامتر اختیاری دارد. |
| 379 | + |
| 380 | + |
| 381 | +* **action**: از نوع ``str`` بوده و میتواند یکی از مقادیر پایین باشد. این مشخص میکند که چه عملیاتی میبایست بر روی Warningها اعمال شود: |
| 382 | + |
| 383 | + .. container:: table |
| 384 | + |
| 385 | + ====================== =================================================================== |
| 386 | + مقدار توضیحات |
| 387 | + ====================== =================================================================== |
| 388 | + ``'default'`` حالت پیشفرض، هر Warning به ازای سطری که در آن قرار دارد یکبار چاپ شود |
| 389 | + ``'error'`` تبدیل رفتار Warning به Exception واقعی - بروز خطا |
| 390 | + ``'ignore'`` نادیده گرفتن Warning |
| 391 | + ``'always'`` Warning هر بار چاپ شود |
| 392 | + ``'module'`` هر Warning به ازای هر ماژول تنها یکبار چاپ شود |
| 393 | + ``'once'`` هر Warning به ازای کل برنامه تنها یکبار چاپ شود |
| 394 | + ====================== =================================================================== |
| 395 | + |
| 396 | +* **category**: نوع Warning را مشخص میکند که میبایست **نام یک subclass از کلاس** ``Warning`` باشد. ارسال آرگومان برای این پارامتر اختیاری است و در صورت عدم ارسال، عمل مشخص شده توسط پارامتر action برای تمام انواع Warningها در برنامه اعمال میگردد. |
| 397 | + |
| 398 | +به نمونه کدهای زیر توجه نمایید: |
| 399 | + |
| 400 | +.. code-block:: python |
| 401 | + :linenos: |
| 402 | +
|
| 403 | + import warnings |
| 404 | + warnings.simplefilter('ignore') |
| 405 | + # $ python3 -Wi sample.py |
| 406 | + # $ python3 -Wignore sample.py |
| 407 | +
|
| 408 | +
|
| 409 | + print('-------Before #01-------') |
| 410 | + warnings.warn('#01') |
| 411 | + print('-------After #01-------') |
| 412 | +
|
| 413 | +:: |
| 414 | + |
| 415 | + -------Before #01------- |
| 416 | + -------After #01------- |
| 417 | + |
| 418 | + |
| 419 | +.. code-block:: python |
| 420 | + :linenos: |
| 421 | +
|
| 422 | + import warnings |
| 423 | + warnings.simplefilter('ignore', DeprecationWarning) |
| 424 | + # $ python3 -Wignore::DeprecationWarning sample.py |
| 425 | + # $ python3 -Wi::DeprecationWarning sample.py |
| 426 | +
|
| 427 | +
|
| 428 | + print('-------Before #02-------') |
| 429 | + warnings.warn('#02') |
| 430 | + print('-------After #02-------') |
| 431 | +
|
| 432 | + print('-------Before #03-------') |
| 433 | + warnings.warn('#03', DeprecationWarning) |
| 434 | + print('-------After #03-------') |
| 435 | +
|
| 436 | +:: |
| 437 | + |
| 438 | + -------Before #02------- |
| 439 | + sample.py:8: UserWarning: #02 |
| 440 | + warnings.warn('#02') |
| 441 | + -------After #02------- |
| 442 | + -------Before #03------- |
| 443 | + -------After #03------- |
| 444 | + |
| 445 | + |
| 446 | +.. code-block:: python |
| 447 | + :linenos: |
| 448 | +
|
| 449 | + import warnings |
| 450 | + warnings.simplefilter('error') |
| 451 | + # $ python3 -We sample.py |
| 452 | + # $ python3 -Werror sample.py |
| 453 | +
|
| 454 | +
|
| 455 | + print('-------Before #04-------') |
| 456 | + warnings.warn('#04') |
| 457 | + print('-------After #04-------') |
| 458 | +
|
| 459 | +
|
| 460 | +:: |
| 461 | + |
| 462 | + -------Before #04------- |
| 463 | + Traceback (most recent call last): |
| 464 | + File "sample.py", line 8, in <module> |
| 465 | + warnings.warn('#04') |
| 466 | + UserWarning: #04 |
| 467 | + |
| 468 | + |
| 469 | +.. tip:: |
| 470 | + |
| 471 | + اعمال Filter در زمان اجرای اسکریپت نیز با استفاده از کلید ``W-`` ممکن میباشد [`اسناد پایتون <https://docs.python.org/3/using/cmdline.html#cmdoption-w>`__] که در هر نمونه کد، معادل دستور اجرای پایتون نیز به صورت کامنت درج شده است. |
| 472 | + |
| 473 | + |
| 474 | +.. tip:: |
| 475 | + |
| 476 | + همانند Exceptionها میتوانید انواع Warning خود را ایجاد نمایید. برای این منظور تنها کافی است یک کلاس ایجاد نمایید که از کلاس ``Warning`` یا یکی از subclassهای آن ارثبری داشته باشد. |
| 477 | + |
| 478 | +.. note:: |
| 479 | + |
| 480 | + این بخش به دلیل وابستگی مبحث Warning با مبحث مهم Exception در زبانبرنامهنویسی پایتون و صرفا به منظور آشنایی خوانندگان با همچنین قابلیتی در این زبان تهیه شده است. ماژول ``warnings`` امکانات گستردهتری را فراهم میآورد که پرداختن به تمام آنها خارج از حوصله این درس میبود، بنابراین علاقهمندان برای مطالعه بیشتر میتوانند به مستندات رسمی پایتون مراجعه نمایند. |
245 | 481 |
|
246 | 482 |
|
247 | 483 |
|
|
0 commit comments