داریوش مهدی پور یقینی
داریوش مهدی پور یقینی
خواندن ۷ دقیقه·۲ سال پیش

فصل هفدهم آموزش پایتون مقدماتی - مدیریت خطاها

سلام دوستان

با ادامه ی کتاب پایتون مقدماتی که به همراه دوست عزیزم جناب مهندس مهدی عباسپور شاهمرس نوشته و چاپ کردیم در خدمتتون هستیم.

https://virgool.io/@mahdi.abbaspour.sh

پایتون دارای دو ویژگی بسیار مهم برای مدیریت خطاهای غیرمنتظره و افزودن امکان اشکال‌‌زدایی در برنامه‌‌های شماست که در ادامه به بررسی هر یک خواهیم‌‌پرداخت.

17-1- مدیریت خطاها و استثنائات[1]

در این فصل از کتاب، بیشتر در مورد این نوع خطاها بحث خواهیم‌‌کرد. لیستی از خطاها و استثنائات استاندارد را به همراه توضیحات، در شکل (17-1) مشاهده می‌‌کنید.

شکل (17-1)
شکل (17-1)


[1]Exceptions

17-2- اظهارات و ادعاها[1]

هر ادعا، یک بررسی عقلانی است که برای شروع تست برنامه‌‌ی خودتان، می‌‌توانید آن را روشن نموده و برای اتمام کار، آن را خاموش‌‌نمایید. به عبارت دیگر، هر ادعا، معادل دستور raise-if و به طور دقیق‌‌تر، raise-if-not است. در این دستور، عبارت مدنظر بررسی می‌‌شود. اگر نتیجه‌‌ی بررسی، Flase بود، یک پیغام خطا صادر می‌‌شود.

ادعاها، توسط دستور assert اجرا می‌‌شوند. این دستور در پایتون نسخه‌‌ی 1.5 معرفی شده‌‌است. به طور معمول، برنامه‌‌نویسان از آن‌‌ها برای بررسی ورودیِ معتبر تابع، در ابتدای تابع و بررسی خروجی معتبر آن، پس از فراخوانی تابع، استفاده می‌‌کنند.

[1]Assertion

17-3- دستور Assert

وقتی پایتون با یک دستور assert مواجه می‌‌شود، دستورات همراه آن را از لحاظ درستی، ارزیابی می‌‌کند. اگر دستورات، نادرست‌‌باشند، پایتون یک AssertionError را صادر می‌‌کند. اگر خود دستور با اشکال مواجه‌‌شود، پایتون از ArgumentExpression به عنوان آرگومان AssertionError استفاده می‌‌کند.

این خطا می‌‌تواند مانند هر خطای دیگری به وسیله‌‌ی بلوک دستوری try-except استفاده‌‌شود. اما اگر عمل‌‌نکرد، برنامه را خاتمه‌‌داده و یک traceback ایجاد می‌‌کند.

مثال شکل (17-2)، نمایان‌‌گر تابعی‌‌است که درجه‌‌ی حرارت را از کلوین[1] به فارنهایت[2] تبدیل می‌‌کند. از آن جایی که صفرِ کلوین، سردترین نقطه است، مقدار منفی برای تابع، به منزله‌‌ی خطا می‌‌باشد.

شکل (17-2)
شکل (17-2)

نتیجه‌‌ی اجرای این مثال، به صورت شکل (17-3) است. همان طوری که مشاهده می‌‌کنید، برای مقدار منفی خطای مدنظر، صادر می‌‌شود.

شکل (17-3)
شکل (17-3)
[1]Kelvin [2]Fahrenheit

17-4- یک Exception چیست؟

این کلمه، دارای معانی مختلفی است که در مهندسی کامپیوتر، بیشتر در معانی استثناو خطا مورد استفاده قرار می‌‌گیرد. هر استثنا یک رویداد[1] است که در طی اجرای یک برنامه رخ می‌‌دهد. این رویداد، جریان عادی دستورالعمل‌‌های برنامه را با اختلال مواجه می‌‌کند. به طور کلی، زمانی که یک اسکریپت پایتون، با وضعیتی مواجه‌‌‌‌شود که نمی‌‌تواند آن را مدیریت کند، یک خطا یا استثنا را تولید می‌‌کند. در نهایت می‌‌توان گفت که، هر استثنا، یک شی پایتون است که خطایی را نشان می‌‌دهد. هنگامی که برنامه‌‌ی پایتون یک استثنا را ایجاد ‌‌کند، دو حالت پیش‌‌رو دارد. یا باید بتواند آن را مدیریت‌‌کند ویا برنامه را خاتمه‌‌دهد.

[1]Event

17-5- مدیریت خطا و استثنا

اگر کد مشکوکی دارید که احتمال رخ‌‌داد خطای برنامه را افزایش می‌‌دهد، با قراردادن آن در بین بلوک try: می‌‌توانید از برنامه‌‌ی خود در مقابل این احتمال محافظت‌‌کنید. بعد از بلوک مذکور، یک دستور except: به همراه یک بلوکِ کد حاوی روش‌‌های مدیریت خطا، خواهیم‌‌داشت. شمای کلی این دستور به شکل (17-4) است.

شکل (17-4)
شکل (17-4)

در ادامه‌‌ی مطلب، چند نکته‌‌ی مهم را در رابطه با این شمای کلی ذکر می‌‌کنیم.

  • هر دستور try می‌‌تواند دارای چندین دستور except باشد. این نکته زمانی می‌‌تواند مفید‌‌باشد که امکان صدور چندین استثنا برای یک بلوک، وجود داشته‌‌باشد.
  • شما می‌‌توانید برای مدیریت همه‌‌ی استثناها، یک عبارت استثنای عمومی ارائه‌‌دهید.
  • بعد از عبارات except می‌‌توان یک عبارت else اضافه‌‌نمود. اگر هیچ یک از استثنائات تعریف‌‌شده، رخ‌‌ندادند، از این بلوک استفاده می‌‌شود. این بلوک برای کدهایی که نیازی به محافظت در برابر خطا ندارند نیز کاربرد دارد.

شکل (17-5)، مثالی از بازکردن فایل و نوشتن متن در آن را نشان می‌‌دهد.

شکل (17-5)
شکل (17-5)

با اجرای این مثال، خروجی برنامه، به شکل (17-6) خواهد بود. همان طوری که می‌‌بینید، به دلیل عدم وجود هرگونه خطای I/O ، متن مدنظر، در فایل مربوطه نوشته‌‌شده و موفقیت‌‌آمیز بودن کار، با عبارتی که در قسمت else داشتیم، نمایش داده‌‌شد.

شکل (17-6)
شکل (17-6)

حال به مثال شکل (17-7) توجه‌‌کنید. در این مثال، یک استثنا را برای حالتی نوشتیم که فایل مدنظر موجود‌‌ نیست و ما سعی در بازکردن آن داریم. با اجرای مثال، عبارت مربوط به خطا، در خروجی چاپ خواهدشد. خروجی آن به شکل (17-8) می‌‌شود.

شکل (17-7)
شکل (17-7)
شکل (17-8)
شکل (17-8)

17-6- عبارت Except بدون نوع مشخص

شما می‌‌توانید از این عبارت بدون مشخص‌‌نمودن نوع استثنای آن، استفاده‌‌کنید. این نوع از try-except، می‌‌تواند تمام رخ‌‌داد استثناها را مدیریت‌‌کند. با وجود این که، نوع مذکور، با پوشش تمام خطاها، می‌‌تواند کار را برای برنامه‌‌نویس راحت‌‌تر نماید، همچنان نمی‌‌تواند علت اصلی مشکل را نمایش‌‌دهد. نحوه‌‌ی استفاده از آن شبیه به مثال موجود در شکل (17-6) است. تنها تفاوت، در این است که نیازی به نوشتن عبارت خطا (برای مثال IOError) نیست.

17-7- عبارت Except با چندین نوع مشخص

شمای کلی این عبارت، به شکل (17-9) خواهدبود. همان گونه که می‌‌بینید، می‌‌توانیم چندین استثنای مهم را به صورت هم‌‌زمان، مدیریت‌‌کنیم.

شکل (17-9)
شکل (17-9)

17-8- عبارت Try-Finally

شما همواره می‌‌توانید از یک بلوک finally به‌‌همراه try استفاده‌‌کنید. در این بلوک، کدهایی قرار می‌‌گیرند که چه خطا داشته‌‌باشیم و چه هیچ خطایی نداشته‌‌باشیم، بایستی اجرا ‌‌شوند. در شکل (17-10)، مثالی ارائه می‌‌دهیم که ترکیبی از چندین نوع از این عبارات را نشان می‌‌دهد.

شکل (17-10)
شکل (17-10)

زمانی که یک استثنا در بلوک try رخ می‌‌دهد، بلافاصله، مترجم پایتون، به بلوک finally منتقل می‌‌شود. بعد از این که تمامی دستورات این بلوک اجرا شدند، دوباره، خطا صادر می‌‌شود. اگر در لایه‌‌ی بالایی، try-except دیگری وجود داشته‌‌باشد، پایتون، مدیریت آن‌‌ها را ادامه می‌‌دهد. در نهایت، با اجرای این قطعه کد، متن "Going to close the file" چاپ می‌‌شود. البته اگر به جای پارامتر w، از پارامتر r استفاده‌‌کنیم، به دلیل بروز خطا، عبارت "Error: can't find file or read data" را خواهیم‌‌داشت.

17-9- آرگومان Exception

هر استثنایی می‌‌تواند یک آرگومان نیز داشته‌‌باشد. این آرگومان حاوی مقداری‌‌است که اطلاعات بیشتری را در مورد آن استثنا ارائه می‌‌دهد. محتوای آرگومان‌‌ها می‌‌تواند متناسب با نوع استثنا، متفاوت‌‌باشد.

اگر کد شما، برای مدیریتِ تنها یک استثنا باشد، می‌‌توانید یک متغیر حاوی نام استثنا، در کنار عبارت except داشته‌‌باشید.همچنین در صورتی که بخواهید، چندین استثنا را به صورت هم‌‌زمان مدیریت‌‌کنید، می‌‌توانید متغیری از نوع تاپل داشته‌‌باشید که هر عنصر آن، یکی از استثنا را پوشش‌‌دهد.

این متغیر می‌‌تواند، تک مقداری ویا چند مقداری باشد. به طور معمول، مقدار آن، در نوع اول، علت خطا و در حالت دوم، علت، شماره و مکان خطا را مشخص می‌‌کند. همانند مثال شکل (17-11)، به راحتی می‌‌توان از این آرگومان استفاده‌‌نمود.

شکل (17-11)
شکل (17-11)

همان طوری که می‌‌بینید، تابعی به همراه بلوک try-except تعریف‌‌کردیم. با اجرای این مثال خروجی شکل (17-12) را خواهیم‌‌داشت که علاوه بر پیغام‌‌خطا، مقداری که موجب صدور این خطا شده‌‌است را نیز چاپ می‌‌کند.

شکل (17-12)
شکل (17-12)

17-10-دستور Raise

در پایتون می‌‌توان به وسیله‌‌ی دستور raise، استثناها را به وجود آورد. شمای کلی این دستور، به صورت شکل (17-13) است.

شکل (17-13)
شکل (17-13)

در این شکل Exception، برای مشخص‌‌نمودن نوع ویا نام استثنا بوده و args برای تعیین مقدار آرگومان به کار می‌‌رود. از آن جایی که، استفاده از آرگومان اختیاری است، اگر تعیین‌‌نشود، خالی در نظرگرفته می‌‌شود. البته آرگومان آخر، یعنی traceback نیز اختیاری‌‌بوده و در عمل، به ندرت استفاده می‌‌شود. اگر مقدار آن تعیین شده‌‌باشد، شیِ ردیابی، برای استثنا به کار می‌‌رود.

هر استثنا می‌‌تواند یک رشته، کلاس ویا شی باشد. اغلب استثنائاتی که خودِ هسته‌‌ی پایتون استفاده می‌‌کند، از نوع کلاس هستند. این نوع، حاوی آرگومانی به عنوان نمونه‌‌ای از آن کلاس، می‌‌باشند. تعریف استثنای جدید، بسیار آسان‌‌بوده و به صورت شکل (17-14) انجام می‌‌شود.

شکل (17-14)
شکل (17-14)

اگر مقدارِ کوچک‌‌تر از یک را برای فراخوانی این تابع ارسال‌‌کنیم، خروجی ما چیزی شبیه به شکل (17-15)، خواهدبود که معادل خطای تعریف شده‌‌است.

شکل (17-15)
شکل (17-15)

نکته: برای دسترسی به هر استثنایی، بایستی عبارت except به همان استثنا، اشاره‌‌کند. کلاس ویا رشته‌‌ی ساده بوردن استثنا، هیچ تفاوتی ایجاد نمی‌‌کند. به عنوان مثال، برای صدور خطای شکل (17-15)، باید این عبارت را به صورت شکل (17-16)، به کار گیریم.

شکل (17-16)
شکل (17-16)

17-11- تعریف خطای سفارشی

در نهایت، پایتون به ما اجازه می‌‌دهد که استثنائات مخصوص خود را با استنتاج از کلاس‌‌های توکار استاندارد، ایجاد‌‌کنیم. برای نمونه، در شکل (17-17)، مثالی مربوط به RuntimeError را با استنتاج از زیرکلاس آن می‌‌سازیم.

در بلوک try، استثناي تعريف‌‌شده توسط کاربر، صادر‌‌شده و در بلوک except ضبط و مدیریت مي‌‌شود. متغیر e نیز برای ایجاد نمونه‌‌ای از کلاس Networkerror به‌‌کار می‌‌رود.

شکل (17-17)
شکل (17-17)

لازم به ذکر است، بعد از تعریف کلاس مدنظر، می‌‌توان استثنای آن را به صورت شکل (17-18) صادر‌‌کرد.

شکل (17-18)
شکل (17-18)

سخن آخر

کتاب پیش رو، حاصل تلاش‌‌های شبانه‌‌روزی گردآورندگان آن می‌‌باشد. همیشه به دنبال راه‌‌ها و مثال‌‌هایی گشتیم تا درک مطالب پیچیده را برای خوانندگان عزیز، آسان‌‌تر نماییم. امید است در این تلاش، موفق بوده‌‌باشیم. هیچ اثر ساخت بشری عاری از نقص نیست. این کتاب نیز از این قاعده، مستثنی نخواهدبود. با این وجود سعی در کاهش هرچه بیشتر این نقایض داشتیم.

امیدواریم خوانندگان عزیز با ارائه‌‌ی نظرات و پیشنهادات خود ما را در هر چه بهتر‌‌نمودن این اثر، یاری نمایند. بدیهی است، استقبال شما عزیزان، مشوقی جهت شروع تالیف کتاب "پایتون پیشرفته" خواهدبود.


کتابکتاب خوانیآموزشپایتونمقدماتی
مدرس دانشگاه، مولف کتاب، برنامه نویس، عاشق هوش مصنوعی مخصوصا یادگیری عمیق، کتاب و مسافرت و گشت و گذار تو طبیعت مخصوصا بکرش رو هم خیلی دوست دارم.
شاید از این پست‌ها خوشتان بیاید