Skip to content

Commit 6329783

Browse files
author
Saeid Darvish
committed
l23: at Exception Hierarchy
1 parent 5f5fa98 commit 6329783

1 file changed

Lines changed: 184 additions & 4 deletions

File tree

lessons/l23.rst

Lines changed: 184 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
:keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون, Data Class, کتابخانه, پایتون, شی گرایی در پایتون
66

77

8-
درس ۲۳: مدیریت خطا در پایتون: Exception ،Error و Warning
8+
درس ۲۳: مدیریت خطا در پایتون: Exception ،Traceback و Exception Handling
99
===================================================================================================
1010

1111
.. figure:: /_static/pages/23-python-exception-error-warning-try.jpg
@@ -171,8 +171,9 @@
171171
این نکته را نیز در نظر بگیرید - همانطور که اگر به خروجی‌های دقت کرده باشید حتما متوجه شده‌اید در دو حالت مربوط به گزارش خطای مربوط به ``SyntaxError`` خبری از سطر ``:Traceback (most recent call last)`` که در حالت خطای زمان اجرای ``TypeError`` مشاهده کردیم، نمی‌باشد. در واقع این سطر تنها در گزارش خطاهایی که پس از اجرای برنامه رخ دهند (Runtime errors)، نمایش داده خواهد شد. در زمان بررسی و ترجمه کد پایتون به بایت‌کد هرجا مشکلی باشد عملیات در همان نقطه متوقف می‌شود و صرفا گزارشی مبنی بر ابراز آن نقطه به برنامه‌نویس ارايه می‌گردد و نه چیزی که بتوان آن را یک گزارش ردیابی با Traceback نامید چرا که هنوز برنامه به اجرا درنیامده و اصلا نیازی به این کار نیست!
172172

173173

174-
Exception handling
175-
~~~~~~~~~~~~~~~~~~~~~~~~
174+
مدیریت خطا (Exception Handling)
175+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
176+
176177
در زبان‌های برنامه‌نویسی صدای اعتراض یک Exception قابل درک و تشخیص است و می‌توان برای آن‌ها فرآیندی را پیش‌بینی کرد که بروز آن‌ها نه تنها باعث اتمام برنامه نشود بلکه برنامه بتواند در مسیر درست به اجرای خود ادامه دهد.
177178

178179
در زبان برنامه‌نویسی پایتون دستور ``try/except`` برای همین منظور فراهم دیده شده است [`اسناد پایتون <https://docs.python.org/3/reference/compound_stmts.html#the-try-statement>`__].
@@ -474,6 +475,36 @@ Exception handling
474475
Successful, closed!
475476

476477

478+
**توجه داشته باشید،** چنانچه بدنه ``try`` شامل دستور ``return`` باشد، آنگاه بدنه دستور ``else`` اجرا نخواهد شد!:
479+
480+
481+
.. code-block:: python
482+
:linenos:
483+
484+
def print_sum_div_first(a, b):
485+
try:
486+
sum = a + b
487+
div = sum / a
488+
return 'Successful'
489+
490+
except Exception as err:
491+
return 'Failed'
492+
493+
else:
494+
return 'Successful, from else!'
495+
496+
result = print_sum_div_first(5, 6) # Successful
497+
print(result)
498+
499+
result = print_sum_div_first(3, 'G') # Failed
500+
print(result)
501+
502+
::
503+
504+
Successful
505+
Failed
506+
507+
477508

478509
``try/finally`` ``try/except/finally`` ``try/except/else/finally``
479510
---------------------------------------------------------------------------------------------
@@ -522,9 +553,158 @@ Exception handling
522553
----> except
523554
----> finally
524555

525-
کاربرد اصلی دستور ``finally`` تمیزکاری یا Cleaning Up کردن کد پس از انجام کاری مشخص است.
556+
حتی اگر زمانی داخل بدنه دستور ``except`` نیز یک Exception رخ دهد، مفسر پایتون اعلام اعتراض آن Exception را موقتا نگه‌می‌دارد تا بدنه دستور ``finally`` به صورت کامل اجرا گردد. در واقع کاربرد اصلی دستور ``finally`` - که تحت هر شرایطی اجرا می‌گردد - تمیزکاری یا Cleaning Up کردن کد پس از انجام کاری مشخص است (پاک کردن فایل‌های موقت، آزادسازی منابع، حذف اشیایی که دیگر مورد نیاز نیستند و...) که از آن معمولا به عنوان Cleanup Handler نیز یاد می‌شود:
557+
558+
559+
.. code-block:: python
560+
:linenos:
561+
562+
def print_sum_div_first(a, b):
563+
try:
564+
sum = a + b
565+
div = sum / a
566+
567+
except TypeError as err:
568+
print(f'{err.__class__.__name__}: ({a}+{b!r})/{a} =', (a+b)/a)
569+
570+
finally:
571+
print('----> finally')
572+
573+
574+
print_sum_div_first(5, 6)
575+
print('*' * 20)
576+
print_sum_div_first(3, 'G')
577+
578+
::
579+
580+
----> finally
581+
********************
582+
----> finally
583+
Traceback (most recent call last):
584+
File "sample.py", line 3, in print_sum_div_first
585+
sum = a + b
586+
TypeError: unsupported operand type(s) for +: 'int' and 'str'
587+
588+
During handling of the above exception, another exception occurred:
589+
590+
Traceback (most recent call last):
591+
File "sample.py", line 15, in <module>
592+
print_sum_div_first(3, 'G')
593+
File "sample.py", line 7, in print_sum_div_first
594+
print(f'{err.__class__.__name__}: ({a}+{b!r})/{a} =', (a+b)/a)
595+
TypeError: unsupported operand type(s) for +: 'int' and 'str'
596+
597+
همانطور که از خروجی نمونه کد بالا مشاهده می‌شود، داخل بدنه دستور ``except``، یک Exception دیگر رخ داده است. نکته قابل توجه این است که حتی در این وضعیت نیز بدنه دستور ``finally`` اجرا شده و سپس وقوع Exception بدنه ``except`` باعث توقف برنامه شده است.
598+
599+
اگر به گزارش Traceback پایتون در این وضعیت دقت نمایید، مشاهده خواهید کرد که این گزارش چقدر کامل است چرا که حتی به ما می‌گوید در هنگام handle کردن یک Exception بوده که Exception دیگری رخ داده است!
600+
601+
602+
**توجه داشته باشید،** چنانچه بدنه ``try`` و ``except`` و ``finally`` شامل دستور ``return`` باشند، آنگاه این دستور ``return`` از بدنه دستور ``finally`` است که اجرا خواهد شد!:
603+
604+
605+
.. code-block:: python
606+
:linenos:
607+
608+
def print_sum_div_first(a, b):
609+
try:
610+
sum = a + b
611+
div = sum / a
612+
return 'Successful'
613+
614+
except Exception as err:
615+
return 'Failed'
616+
617+
else:
618+
return 'Successful, from else!'
619+
620+
finally:
621+
return '---------->finally!'
622+
623+
result = print_sum_div_first(5, 6) # Successful
624+
print(result)
625+
626+
result = print_sum_div_first(3, 'G') # Failed
627+
print(result)
628+
629+
::
630+
631+
---------->finally!
632+
---------->finally!
633+
634+
635+
گاهی تنها از دستور ``finally`` در کنار ``try`` استفاده می‌گردد، یعنی بدون حضور هیچ‌گونه دستور ``except`` به صورت ``try/finally``. می‌توان از این قالب برای زمانیکه رخداد Exception و مدیریت آن برایمان اهمیتی نداشته باشد، بهره بگیریم. با این حال به نمونه کد زیر توجه نمایید:
636+
637+
638+
.. code-block:: python
639+
:linenos:
640+
641+
def print_sum_div_first(a, b):
642+
try:
643+
sum = a + b
644+
div = sum / a
645+
print(f'----> Result: {div}')
646+
647+
finally:
648+
print('--------> Finished!')
649+
650+
651+
print_sum_div_first(5, 6)
652+
print('*' * 30)
653+
print_sum_div_first(3, 'G')
654+
655+
::
656+
657+
----> Result: 2.2
658+
--------> Finished!
659+
******************************
660+
--------> Finished!
661+
Traceback (most recent call last):
662+
File "sample.py", line 13, in <module>
663+
print_sum_div_first(3, 'G')
664+
File "sample.py", line 3, in print_sum_div_first
665+
sum = a + b
666+
TypeError: unsupported operand type(s) for +: 'int' and 'str'
667+
668+
به هر حال Exception بدون handler باعث توقف اجرای برنامه می‌شود اما اگر داخل بدنه ``finally`` شامل دستور ``return`` باشد، آنگاه مفسر پایتون از اعلام Exception رخ داده که در حال حاظر به صورت موقت نگه‌داشته است تا اجرای بدنه ``finally`` به پایان برسد، صرف نظر خواهد کرد!:
669+
670+
.. code-block:: python
671+
:linenos:
672+
673+
def print_sum_div_first(a, b):
674+
try:
675+
sum = a + b
676+
div = sum / a
677+
print(f'----> Result: {div}')
678+
679+
finally:
680+
print('--------> Finished!')
681+
return None
682+
683+
684+
print_sum_div_first(5, 6)
685+
print('*' * 30)
686+
print_sum_div_first(3, 'G')
687+
688+
::
689+
690+
----> Result: 2.2
691+
--------> Finished!
692+
******************************
693+
--------> Finished!
694+
695+
696+
مدیریت خطای تودرتو (Nested Exception Handling)
697+
---------------------------------------------------
698+
699+
به صورت کلی بدنه هر یک از دستورهای ``try`` ، ``except`` ، ``else`` ، ``finally`` به خودی‌خود می‌توانند شامل یک دستور ``try/except/else/finally`` دیگر باشد. هر جا که کدی نوشته شود آنجا نیز احتمال بروز Exception وجود دارد و هر جا که احتمال بروز Exception وجود داشته باشد به یک handler برای آن نیاز است.
700+
701+
البته از آنجا که در یکی از بندهای فلسفه پایتون آمده: `PEP 20: Flat is better than nested <https://www.python.org/dev/peps/pep-0020/>`__ انجام این‌کار چندان پایتونی نمی‌باشد و برنامه‌نویس احتمالا می‌تواند با کمی دقت بیشر از ساختار تودرتو پرهیز کند و کدی به مراتب خواناتر توسعه دهد. به هر حال امکان این کار در زبان برنامه‌نویسی پایتون برای برنامه‌نویس محفوظ نگه‌داشته شده است.
702+
703+
526704

527705

706+
Exception Hierarchy
707+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
528708

529709

530710

0 commit comments

Comments
 (0)