|
177 | 177 |
|
178 | 178 | در زبانهای برنامهنویسی صدای اعتراض یک Exception قابل درک و تشخیص است و میتوان برای آنها فرآیندی را پیشبینی کرد که بروز آنها نه تنها باعث اتمام برنامه نشود بلکه برنامه بتواند در مسیر درست به اجرای خود ادامه دهد. |
179 | 179 |
|
180 | | -در زبان برنامهنویسی پایتون دستور ``try/except`` برای همین منظور فراهم دیده شده است [`اسناد پایتون <https://docs.python.org/3/reference/compound_stmts.html#the-try-statement>`__]. |
| 180 | +در زبان برنامهنویسی پایتون دستور ``try/except`` برای همین منظور فراهم دیده شده است [`اسناد پایتون <https://docs.python.org/3/reference/compound_stmts.html#the-try-statement>`__] و در ادامه به بررسی انواع ساختار قابل پیادهسازی از این دستور خواهیم پرداخت. |
181 | 181 |
|
182 | 182 | ``try/except`` |
183 | 183 | ------------------------ |
|
400 | 400 | شی Exception که توسط دستور ``except`` دریافت میگردد تنها در داخل بدنه همان دستور ``except`` در دسترس خواهد بود، چرا که بلافاصله پس از اتمام دستورات داخل بدنه آن ``except``، شی مذکور نیز به صورت خودکار حذف میگردد. |
401 | 401 |
|
402 | 402 |
|
403 | | - |
404 | | - |
405 | | - |
406 | | - |
407 | 403 | ``try/except/else`` |
408 | 404 | ------------------------ |
409 | 405 |
|
|
681 | 677 | ****************************** |
682 | 678 | --------> Finished! |
683 | 679 |
|
| 680 | +روند انتشار Exception |
| 681 | +---------------------------- |
| 682 | + |
| 683 | +در تمام مثالهایی که در این بخش ارائه شد، برای سادهسازی مطلب تنها به بررسی مدیریت خطا داخل یک تابع پرداختیم. ولی باید این مورد را در نظر داشته باشید، زمانی که یک Exception رخ میدهد، این Exception به ترتیب مراحل فراخوانی را به ابتدای اجرا در برنامه طی میکند و هر بار چنانچه یک handler (دستور ``try`` با ``except`` مناسب) پیدا نشود، این Exception به مرحله پیشتر تحویل داده میشود تا شاید یک handler برای آن پیدا شود. این روند تا رسیدن به اسکریپت (فایل py. اصلی برنامه) ادامه مییابد و در صورت عدم پیشبینی handler آنگاه Exception در این نقطه بروز و منجر به توقف کل برنامه میگردد. به عنوان مثال نمونه کد زیر را در نظر بگیرید: |
| 684 | + |
| 685 | + |
| 686 | +.. code-block:: python |
| 687 | + :linenos: |
| 688 | +
|
| 689 | + def print_sum_div_first(a, b): |
| 690 | + sum = a + b |
| 691 | + div = sum / a |
| 692 | + print(div) |
| 693 | +
|
| 694 | +
|
| 695 | + def action(a, b): |
| 696 | + try: |
| 697 | + if isinstance(a, int): |
| 698 | + print_sum_div_first(a, b) |
| 699 | +
|
| 700 | + except ZeroDivisionError as err: |
| 701 | + print(f'[action function ERROR!!!] {err.__class__.__name__}') |
| 702 | +
|
| 703 | +
|
| 704 | + try: |
| 705 | + action(5, 6) # Successfully |
| 706 | + action(0, 8) # raise ZeroDivisionError |
| 707 | + action(3, 'G') # raise TypeError |
| 708 | +
|
| 709 | + except Exception as err: |
| 710 | + print(f'[module ERROR!!!] {err.__class__.__name__}') |
| 711 | +
|
| 712 | +:: |
| 713 | + |
| 714 | + 2.2 |
| 715 | + [action function ERROR!!!] ZeroDivisionError |
| 716 | + [module ERROR!!!] TypeError |
| 717 | + |
| 718 | +در نمونه کد بالا همانطور که مشخص است تمام Exceptionها در داخل تابع ``print_sum_div_first`` رخ میدهد ولی از آنجا که این تابع فاقد handler میباشد، Exceptionها به یک مرحله قبلتر یعنی تابع ``action`` تحویل میگردند، ولی این تابع تنها یک handler برای ``ZeroDivisionError`` داشته پس تمامی Exceptionهای احتمالی دیگر از جمله ``TypeError`` به یک مرحله قبلتر تحویل و خوشبختانه در آنجا handle میشوند! |
| 719 | + |
| 720 | + |
684 | 721 |
|
685 | 722 | مدیریت خطای تودرتو (Nested Exception Handling) |
686 | 723 | --------------------------------------------------- |
|
690 | 727 | البته از آنجا که در یکی از بندهای فلسفه پایتون آمده: `PEP 20: Flat is better than nested <https://www.python.org/dev/peps/pep-0020/>`__ انجام اینکار چندان پایتونی نمیباشد و برنامهنویس احتمالا میتواند با کمی دقت بیشر از ساختار تودرتو پرهیز کند و کدی به مراتب خواناتر توسعه دهد. به هر حال امکان این کار در زبان برنامهنویسی پایتون برای برنامهنویس محفوظ نگهداشته شده است. |
691 | 728 |
|
692 | 729 |
|
| 730 | +کارایی (Performance) |
| 731 | +---------------------------- |
| 732 | + |
| 733 | +همیشه این سوال مطرح میشود که آیا بهتر است با کنترل شرط و پیادهسازی چندین دستور ``if`` از بروز Exception جلوگیری کنیم یا خیلی ساده این وظیفه را به یک ساختار handler بسپاریم. کدام روش کارایی بهتری دارد؟ |
| 734 | + |
| 735 | +زبان برنامهنویسی پایتون از نظریه «درخواست بخشش راحتتر از کسب اجازه است» پیروی میکند [`EAFP: Easier to ask for forgiveness than permission <https://docs.python.org/3/glossary.html?highlight=eafp#term-eafp>`__]. بر همین اساس پایتون به صورت پیشفرض تمام مقادیر را صحیح فرض میکند و زمانی اگر خلاف این فرض رخ دهد، آنگاه برای عرض پوزش به دنبال یک handler مناسب میگردد! |
| 736 | + |
| 737 | +مطمئنا سربار handle کردن یک Exception از یک دستور ``if`` بیشتر است ولی تنها وقتی یک Exception به handler نیاز پیدا میکند که رخ بدهد! پیشنهاد پایتونی برای این مسئله ترجیح بر استفاده از دستور ``try/except`` میباشد تا دستور ``if``، چرا که هم خوانایی کد بیشتر میشود و هم از آنجایی که در صورت استفاده از دستور ``if`` روند اجرای کنترل و بررسی شرط هربار در برنامه رخ میدهد ولی عمل جستجو برای یافتن ``except`` مناسب تنها در زمان رخ دادن Exception انجام خواهد شد، کارایی بهتری کسب میگردد. |
| 738 | + |
| 739 | + |
| 740 | +[`مطالعه بیشتر: پرسش و پاسخ مرتبط در StackOverflow <https://stackoverflow.com/q/7604636>`__] |
| 741 | + |
693 | 742 |
|
694 | 743 |
|
695 | 744 | Exception Hierarchy |
|
0 commit comments