Python Learningاز صفر تا نوشتن پروژه از حفظ
درس ۸ · ابزارهای پروژه

خطاها: try، except و raise

حدود ۴۵ دقیقه۳ تمرین۶ سؤال آزمون
بعد از این درس می‌توانی:
  • پیام خطا (traceback) را بخوانی و بفهمی کجا و چرا است
  • با try/except جلوی بسته شدن برنامه را بگیری
  • خودت با raise ValueError(...) خطا بسازی
  • nan و inf و دلیل خطرناک بودنشان را بشناسی

خواندن پیام خطا

اجرا کن

این را اجرا کن

Ctrl + Enter

پیام از پایین خوانده می‌شود: آخرین خط نوع خطا (ValueError) و دلیل آن را می‌گوید، خط‌های بالاتر کجا (شماره‌ی خط).

خطامعمولاً یعنی
SyntaxErrorنگارش غلط: : یا پرانتز یا کوتیشن جا افتاده
IndentationErrorتورفتگی نامرتب
NameErrorاسمی که تعریف نشده (یا غلط املایی)
TypeErrorنوع نامناسب؛ مثل 'a' + 1
ValueErrorنوع درست ولی مقدار نامعتبر؛ مثل int('abc')
KeyErrorکلید در دیکشنری نیست
OSErrorمشکل فایل: باز نشد، اجازه نداشت، …

try / except: گرفتن خطا

اجرا کن

خودت امتحان کن

Ctrl + Enter

اگر داخل try خطایی رخ دهد، بقیه‌ی try رد می‌شود و except اجرا می‌شود. اگر خطا نباشد، except اجرا نمی‌شود.

چند نوع خطا و خود پیام خطا

اجرا کن

خودت امتحان کن

Ctrl + Enter
در پروژه‌ی فروشگاه

تابع run در خط ۸۵ پروژه تا خط ۹۱ پروژه همه‌ی دکمه‌ها را داخل try اجرا می‌کند و پیام خطا را با messagebox نشان می‌دهد. load در خط ۲۰ پروژه تا خط ۲۶ پروژه هم با try جلوی کرش کردن برنامه با فایل خراب را می‌گیرد.

تمرین

تبدیل امن

تابع to_number(text) بنویس که متن را با float به عدد تبدیل کند؛ اگر نشد (ValueError) مقدار None برگرداند.

Ctrl + Enter
دیدن راه‌حل (اول خودت تلاش کن)
def to_number(text):
    try:
        return float(text)
    except ValueError:
        return None

raise: خودت خطا بساز

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

اجرا کن

خودت امتحان کن

Ctrl + Enter
در پروژه‌ی فروشگاه

همه‌ی متدهای کلاس Shop ورودی را چک می‌کنند و با raise ValueError متوقف می‌شوند؛ مثلاً خط ۳۰ پروژه، خط ۳۸ پروژه و خط ۵۷ پروژه.

nan و inf: عددهای عجیب

اجرا کن

خودت امتحان کن

Ctrl + Enter
حواست باشد

هر مقایسه‌ای با nan نادرست است. برای همین چک min(...) < 0 اجازه می‌داد کاربر nan تایپ کند. راه درست: 0 <= x < float('inf') که nan و inf را هم رد می‌کند.

در پروژه‌ی فروشگاه

این باگ واقعاً در برنامه بود و در خط ۳۱ پروژه درست شد: if not all(0 <= x < float('inf') for x in (buy, sell, qty)):.

تمرین

چک قیمت

تابع check_price(p) بنویس که اگر p منفی، nan یا بی‌نهایت بود ValueError با پیام 'عدد منفی یا نامعتبر مجاز نیست' پرتاب کند، وگرنه p را برگرداند.

Ctrl + Enter
دیدن راه‌حل (اول خودت تلاش کن)
def check_price(p):
    if not 0 <= p < float('inf'):
        raise ValueError('عدد منفی یا نامعتبر مجاز نیست')
    return p
تمرین

تابع run کوچک

تابع safe_run(action) بنویس: action() را صدا بزند و 'ok' برگرداند؛ اگر ValueError رخ داد، متن خطا را برگرداند.

Ctrl + Enter
دیدن راه‌حل (اول خودت تلاش کن)
def safe_run(action):
    try:
        action()
        return 'ok'
    except ValueError as exc:
        return str(exc)

آزمون این درس

برای گذراندن این درس حداقل ۸۰٪ جواب درست لازم است. هر چند بار خواستی می‌توانی دوباره امتحان بدهی.

۱. در پیام خطا، نوع خطا کجا نوشته می‌شود؟
۲. int('abc') چه خطایی می‌دهد؟
۳. وقتی داخل try خطا رخ نمی‌دهد، except …
۴. raise ValueError('x') چه می‌کند؟
۵. float('nan') < 0 چیست؟
۶. except (ValueError, OSError) as exc: یعنی