پث‌وایز

شروع برنامه‌نویسی با پایتون (Intro to Python) · درس ۱۰ از ۱۲ · ۱۲ دقیقه

خوندن پیام‌های خطا (Reading Errors)

پیام خطا یعنی پایتون داره بهت می‌گه کجا وایستاد و چرا. یه traceback رو از پایین به بالا می‌خونی، شش تا خطایی رو که مبتدی‌ها بیشتر از همه می‌بینن می‌شناسی، و یه خطای قابل‌انتظار رو با try و except می‌گیری.

کالبدشکافی یه traceback

اول خط آخر رو بخون

وقتی یه برنامه می‌خوابه، پایتون یه traceback (ردِ فراخوانی‌ها) چاپ می‌کنه. با Traceback (most recent call last): شروع می‌شه، بعد هر فراخوانی‌ای رو که وسطش بوده به شکل File "...", line N فهرست می‌کنه و خط کدی که خطا داده رو زیرش می‌نویسه. خط آخر مهم‌ترینه: نوع خطا و یه پیام، مثل TypeError: can only concatenate str (not "int") to str. اول اون رو بخون تا بفهمی چی خراب شده، بعد شماره‌ی خط درست بالاش رو تا بفهمی کجا.

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

name = "Sara"
age = 30
print(name + " is " + age)

خروجی

Traceback (most recent call last):
  File "/home/sara/app.py", line 3, in <module>
    print(name + " is " + age)
          ~~~~~~~~~~~~~~^~~~~
TypeError: can only concatenate str (not "int") to str

این پایتون 3.11‌ـه که یه فایل ذخیره‌شده به اسم /home/sara/app.py رو اجرا می‌کنه؛ خط File برای تو آدرس فایل خودت رو نشون می‌ده. پایتون 3.10 و قدیمی‌تر اون خط ~ و ^ زیر کد رو نمی‌کشن، ولی بقیه‌ش همینه. خط آخر: چی (متن به‌علاوه‌ی عدد). line 3: کجا.

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

برنامه‌ی نگار می‌خوابه و یه traceback ده‌خطی چاپ می‌کنه. اول کدوم بخش رو باید بخونه؟

  1. خط اول، Traceback (most recent call last):
  2. خط آخر، با نوع خطا و پیامش
  3. طولانی‌ترین خط
  4. هیچ‌کدوم؛ باید برنامه رو از اول بنویسه
جواب رو ببین

خط آخر، با نوع خطا و پیامش

درسته. خط آخر می‌گه چی خراب شده، مثلاً TypeError و دلیلش. File ... line N درست بالاش می‌گه کجا.

قدم‌به‌قدم ببین

  1. خط 1 و 2 بدون مشکل اجرا می‌شن

    برنامه‌ی سه‌خطی با شماره‌ی خط‌هاش. فلش اجرا از خط 1 رد شده و روی خط 2 وایستاده، و هر دو تیک خوردن: نگه داشتن "Sara" و 30 مشکلی نداره. خط 3 هنوز اجرا نشده، پس پنل out خالیه.

  2. خط 3 سر + age خطا می‌ده: str + int

    فلش می‌رسه به خط 3، که یه ضربدر خورده. تیکه‌ی + age دورش خط کشیده شده و کنارش برچسب str + int هست: پایتون داره متن "Sara is " رو به عدد 30 می‌چسبونه، کاری که + بلد نیست، پس همین‌جا وایمیسته و هیچی چاپ نمی‌شه.

  3. traceback: اول 1، بعد 2

    یه کارت traceback با سه ردیف ظاهر می‌شه: Traceback، line 3 و TypeError. نشانگرهای شماره‌دار ترتیب خوندن رو نشون می‌دن: 1 روی ردیف آخرِ پررنگ، یعنی TypeError، که می‌گه چی خراب شده، و 2 روی line 3، که می‌گه کجا.

  4. خط 3 درست شد و Sara is 30 چاپ می‌شه

    خط 3 به شکل print(f"{name} is {age}") بازنویسی شده، یه f-string که خودش age رو تبدیل به متن می‌کنه. حالا هر سه خط تیک دارن، پنل out نشون می‌ده Sara is 30، و کارت traceback قبلی کم‌رنگ شده. فقط یه خط عوض شد و برنامه دوباره اجرا شد.

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

امید یه برنامه‌ی دوخطی اجرا می‌کنه: print("start")، بعد print(10 / 0). چی می‌بینه؟

  1. فقط یه خطا؛ چون فایل یه اشتباه داره هیچی اجرا نمی‌شه
  2. start، بعد یه traceback که با ZeroDivisionError: division by zero تموم می‌شه
  3. start، بعد 0
  4. start، و دیگه هیچی
جواب رو ببین

start، بعد یه traceback که با ZeroDivisionError: division by zero تموم می‌شه

درسته. تقسیم بر صفر یه خطای زمان اجراست: پایتون فقط وقتی به خط 2 می‌رسه پیداش می‌کنه، پس خط 1 قبلش start رو چاپ کرده.

دو جور خطا

خطای نوشتاری (Syntax): قبل از اجرای هر چیزی

کد پایتون درستی نیست: یه دونقطه یا پرانتز یا گیومه جا افتاده، یا توی if به‌جای == نوشتی =. پایتون اول کل فایل رو چک می‌کنه، پیداش می‌کنه و هیچی اجرا نمی‌کنه، حتی خط‌های بالای اون.

اسم‌هاش: SyntaxError، و IndentationError برای تورفتگی‌هایی که با هم جور نیستن.

خطای زمان اجرا (Runtime): وسط اجرا

کد درسته، ولی یه قدمش با این مقدارها انجام‌شدنی نیست: تقسیم بر صفر، کلیدی که وجود نداره، متن به‌علاوه‌ی عدد.

همه‌ی خط‌های قبلش اجرا شدن، پس ممکنه اول یه مقدار خروجی ببینی.

print("hi")
x = 5
if x > 3
    print("big")

خروجی

  File "/home/sara/app.py", line 3
    if x > 3
            ^
SyntaxError: expected ':'

یه خطای نوشتاری: خبری از سرتیتر Traceback نیست، و hi اصلاً چاپ نمی‌شه، با اینکه خط 1 مشکلی نداره، چون پایتون اصلاً شروع نکرد. علامت ^ جایی رو نشون می‌ده که دونقطه جا افتاده. (خروجی پایتون 3.11؛ نسخه‌های قدیمی‌تر ممکنه فقط بگن invalid syntax.)

شش تایی که بیشتر از همه می‌بینی

  • NameError: name 'totl' is not defined: غلط تایپی، یا اسمی که قبل از مقدار گرفتن ازش استفاده شده.
  • TypeError: can only concatenate str (not "int") to str: قاطی کردن نوع‌ها؛ از f-string یا str() استفاده کن.
  • ValueError: invalid literal for int() with base 10: 'abc': نوعش درسته، ولی int() نمی‌تونه این مقدار رو تبدیل کنه.
  • IndexError: list index out of range: جایی بعد از آخر لیست؛ آخرین جا len - 1‌ـه.
  • KeyError: 'coffee': کلیدی که توی دیکشنری نیست؛ با in چکش کن، یا از get استفاده کن.
  • ZeroDivisionError: division by zero: تقسیم بر 0، اغلب یه شمارنده که آخرش خالی از آب دراومده.

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

هر خطا رو به علت معمولش وصل کن

جواب رو ببین
  • NameError → اسمی که وجود نداره، اغلب یه غلط تایپی
  • TypeError → نوع نامناسب برای اون کار، مثل متن + عدد
  • IndexError → جایی بعد از آخر یه لیست
  • KeyError → کلیدی که توی دیکشنری نیست

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

  1. total = 10
  2. bonus = 5
  3. print(totl + bonus)
جواب رو ببین

اشکال توی خط ۳.

درسته. totl غلط تایپیِ total‌ـه. پایتون با NameError: name 'totl' is not defined وایمیسته، و نسخه‌های جدیدش حتی اضافه می‌کنن Did you mean: 'total'?

TRY و EXCEPT

خطایی که انتظارش رو داری بگیر

بعضی خطاها باگ نیستن؛ کارهایی‌ان که کاربرها می‌کنن. اگه یکی موقع پرسیدن سنش abc تایپ کنه، int(...) یه ValueError می‌ده. خط‌های پرخطر رو زیر try: بذار و کاری که باید به‌جاش بشه رو زیر except ValueError:. اگه بلوک try بی‌مشکل اجرا بشه، except رد می‌شه؛ اگه ValueError پیش بیاد، پایتون به‌جای خوابیدن می‌پره سراغ except. اسم خطای مشخصی رو که انتظارش رو داری بنویس، تا باگ‌های واقعی همچنان دیده بشن.

توی یه برنامه‌ی واقعی متن از age = int(input("Age? ")) میاد. پایین یه متغیر ساده‌ست تا خروجی ثابت بمونه.

text = "abc"
try:
    age = int(text)
    print("Next year:", age + 1)
except ValueError:
    print("Please type a number")

خروجی

Please type a number

int("abc") سر خط اول بلوک try خطا می‌ده، پس print زیرش هیچ‌وقت اجرا نمی‌شه و پایتون مستقیم می‌ره سراغ بلوک except. خبری از traceback نیست و برنامه ادامه پیدا می‌کنه.

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

text = "29"
try:
    age = int(text)
    print("Next year:", age + 1)
except ValueError:
    print("Please type a number")
  1. Next year: 30
  2. Please type a number
  3. Next year: 30
    Please type a number
  4. Next year: 291
جواب رو ببین
Next year: 30

درسته. int("29") کار می‌کنه، پس کل بلوک try اجرا می‌شه و except رد می‌شه.

یه عادت برای رفع خطا (debugging)

  1. خط آخر رو بخون

    نوع خطا و پیامش بهت می‌گه دنبال چه جور مشکلی بگردی.

  2. برو سراغ شماره‌ی خط

    اون خط رو نگاه کن، و اگه خطای نوشتاریه خط بالاییش رو هم.

  3. مقدارهای درگیر رو چاپ کن

    درست قبل از خط خراب print(type(x), x) رو اضافه کن تا ببینی واقعاً چی داری، نه چیزی که فکر می‌کردی.

  4. یه چیز رو عوض کن و دوباره اجرا کن

    هر بار یه تغییر بهت می‌گه کدوم تغییر درستش کرد. گیر کردی؟ دقیقاً خط آخر پیام رو جست‌وجو کن؛ معمولاً یکی قبلاً توضیحش داده.

مرور درس

  • traceback با ErrorType: message تموم می‌شه؛ اول همون خط آخر رو بخون، بعد شماره‌ی خط بالاش رو.
  • خطای نوشتاری برنامه رو قبل از اجرای هر چیزی متوقف می‌کنه؛ خطای زمان اجرا وسط کار پیش میاد، بعد از اینکه خط‌های قبلی چاپ کردن.
  • شش تای رایج: NameError، TypeError، ValueError، IndexError، KeyError، ZeroDivisionError.
  • خطی که گزارش می‌شه جاییه که پایتون مشکل رو دیده؛ توی خطای نوشتاری خط بالایی رو هم چک کن.
  • try / except SomeError خطایی رو که انتظارش رو داری مدیریت می‌کنه، مثل وقتی کاربر به‌جای عدد abc تایپ می‌کنه.

فقط نخونش، نگهش دار

پث‌وایز هر ایده رو درست قبل از اینکه فراموشش کنی با یه سؤال کوتاه برمی‌گردونه. رایگان روی اندروید و وب، به فارسی و انگلیسی.

Cafe Bazaar Myket باز کردن نسخه‌ی وب

همه‌ی درس‌های این دوره

  1. اولین برنامه‌ت (Your First Program)
  2. متغیرها: اسم برای مقدارها (Variables)
  3. رشته‌ها: کار با متن (Strings)
  4. ورودی و نوع داده‌ها (Input and Types)
  5. تصمیم‌گیری با if (Conditionals)
  6. لیست‌ها: کلی مقدار یه‌جا (Lists)
  7. حلقه‌ها: دوباره و دوباره (Loops)
  8. تابع‌ها: به یه کار اسم بده، دوباره استفاده‌ش کن (Functions)
  9. دیکشنری‌ها: پیدا کردن با اسم (Dictionaries)
  10. خوندن پیام‌های خطا (Reading Errors)
  11. ذخیره و خوندن فایل (Files)
  12. پروژه‌ی آخر: حساب خرج‌ها (Final Project)