مرکز آموزش میهن وب هاست

مرکز آموزش میهن وب هاست

درک خروجی خطای Python (Traceback)

پرینت این مقاله پرینت این مقاله

پایتون هنگام بروز یک استثنا (Exception) در کد شما، خروجی خطا یا "Traceback"، نمایش می‌دهد. خروجی خطای پایتون اطلاعات ارزشمندی را ارائه خواهد داد که می‌تواند به شما در تشخیص و رفع دلیل بروز استثنا در کد کمک کند. 
خروجی خطای پایتون:
خروجی خطا گزارشی از فراخوانی‌های تابعی (Function Calls) است که داخل کد شما در یک نقطه خاص انجام شده‌اند. به این خروجی‌ها نام‌های مختلفی از جمله Stack Trace, Stack Traceback, Backtrace و … داده می‌شود. در پایتون، این خروجی اشتباه "Traceback" نام دارد. وقتی برنامه به یک استثنا ختم می‌شود، پایتون خروجی خطای فعلی را چاپ می‌کند تا به شما نشان دهد چه چیزی اشتباه بوده است.
در مثال تصویر1 کلمه name در ورودی تابع  print به‌ اشتباه تایپ شده و خطای Traceback خروجی نیز در تصویر2 آورده شده است.

تصویر(1)


تصویر(2)

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

در خروجی خطای بالا، استثنا از نوع NameError بوده و این معنا را دارد که به نامی (متغیر، تابع، کلاس) اشاره شده که در برنامه تعریف نشده است. در این مورد، نام مورد اشاره nam است. خط آخر این خروجی اطلاعات کافی برای کمک به شما در رفع مشکل را ارائه می‌دهد. جست‌وجوی کد برای نام nam که اشتباه تایپی دارد، شما را به مسیر درست هدایت می‌کند.

بررسی کلی Traceback در پایتون
هر traceback در پایتون شامل چندین بخش مهم است. در تصویر3 یک traceback از کد تست و قسمت‌های مختلف آن بیان گردیده است:


تصویر(3)

در پایتون، بهترین روش برای خواندن traceback این است که آن را از پایین‌به‌بالا بخوانید:

  1.  باکس آبی:

    خط آخر traceback پیام خطا را نشان می‌دهد. این خط شامل نام استثنای رخ‌داده است. 
  2. باکس سبز:

    بعد از نام استثنا، پیام خطا قرار دارد. این پیام معمولاً اطلاعات مفیدی را برای درک دلیل بروز استثنا ارائه می‌دهد.
  3. باکس زرد:

    در بخش‌های بالاتر traceback، فراخوانی‌های مختلف توابع به ترتیب از پایین‌ به‌ بالا (جدیدترین تا قدیمی‌ترین) نمایش داده شده‌اند. هر فراخوانی با یک ورودی دوخطی بیان می گردد:
    • خط اول: شامل اطلاعاتی مانند نام فایل، شماره خط و نام ماژول است که مشخص می‌کند کد در کجا قرار دارد.

    • خط دوم (خط‌قرمز): کدی که در این فراخوانی اجرا شده است.

این ساختار به شما کمک می‌کند تا خطا را به‌صورت مرحله‌ای دنبال کرده و علت اصلی آن را بیابید.

بررسی دقیق خروجی Traceback

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

در کد تصویر4 تلاش شده تا تابعی برای جمع دو عدد نوشته شود؛


تصویر(4)

نتیجه مطلوب در خط 1 و 2 حاصل شده است و هیچ خطایی وجود ندارد.
اما اگر بخواهید مقدار جمع دو عدد را داخل متن برنامه در خروجی نمایش دهید و نام یک متغیر را به اشتباه تایپ کنید؛ traceback به صورت تصویر5 ایجاد می شود.


تصویر(5)

بار دیگر، در مواجهه با traceback در پایتون، بهتر است از پایین‌به‌بالا خروجی را بررسی کنید.

  1. شروع از خط آخر:

    خط آخر traceback نشان می‌دهد که استثنا یک TypeError بوده است. پیام پس از نوع استثنا (هر موردی که بعد از علامت دونقطه ": " آمده) اطلاعات مفیدی ارائه می‌دهد. در این مورد، بیان می‌کند که تابع ()add_numbers با یک آرگومان کلیدی فراخوانی شده که انتظار نمی‌رفت. لازم به ذکر است که نام آرگومان ناشناخته نیز مشخص شده است: bb 
  2. حرکت به بالا:

    با حرکت به سمت خطوط بالاتر، می‌بینید که خط کدی که باعث بروز استثنا شده است، فراخوانی ()add_numbers در انتهای فایل ex2.py می باشد.
  3. اطلاعات بیشتر:

    خط بعدی مسیر فایلی را نشان می‌دهد که کد در آن قرار دارد. همچنین شماره خطی که کد در آن پیدا شده و ماژول مربوطه در آن موجود است نیز نمایش داده خواهد شد. در این مورد، چون کد تست شده از هیچ ماژول پایتون دیگری استفاده نمی‌کند، <module> نشان داده می‌شود و این معنا را دارد که فایل موردنظر همان فایل اجرایی است. 

برخی از رایج‌ترین خطاهای Traceback در پایتون: 

یادگیری نحوه خواندن traceback در پایتون زمانی که برنامه شما استثنایی ایجاد می‌کند، می‌تواند بسیار مفید باشد. شناخت برخی از traceback ‌های رایج نیز روند عیب‌یابی را تسریع می نماید.

در ادامه، تعدادی از استثناهای رایج که ممکن است با آن‌ها مواجه شوید، دلایل وقوع آنان، معنا و اطلاعاتی که می‌توانید در traceback مربوطه پیدا کنید آورده شده است:

1. AttributeError

خطای AttributeError زمانی ایجاد می‌شود که شما سعی می‌کنید به یک ویژگی (attribute) روی یک شیء دسترسی پیدا کنید که آن ویژگی برای شیء تعریف نشده است. 

در زیر مثالی از بروز AttributeError  آورده شده است:

در مثال تصویر6 کتابخانه math ایمپورت شده و همان‌طور که می‌دانید این کتابخانه شامل تابع square نیست.


تصویر(6)

بنابراین، تلاش برای دسترسی به این ویژگی با خطای تصویر7 مواجه شده است.


تصویر(7)

2. ImportError

ImportError زمانی رخ می‌دهد که مشکلی در یک دستور import رخ دهد. شما با این استثنا یا زیر کلاس آن (ModuleNotFoundError)، مواجه خواهید شد اگر:

  • ماژولی که سعی در وارد کردن آن دارید پیدا نشود.

  • تلاش نمایید چیزی را از یک ماژول وارد کنید که در آن ماژول وجود ندارد.

در زیر مثالی از بروز ImportError و ModuleNotFoundError آورده شده است:

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


تصویر(8)


تصویر(9)

3. IndexError

IndexError زمانی ایجاد می‌شود که شما سعی کنید از یک توالی مانند list یا tuple ایندکسی را بازیابی کنید، درحالی‌که ایندکس موردنظر وجود نداشته یا خارج از محدوده معتبر آن توالی است. 

در تصویر10 مثالی آورده شده که باعث بروز IndexError می‌شود.


تصویر(10)

در این مثال، لیست numbers تنها سه عنصر دارد (ایندکس‌های 0، 1 و 2).

وقتی سعی می‌کنید به ایندکس 5 دسترسی پیدا کنید، که خارج از محدوده لیست است، یک IndexError مطابق تصویر11 ایجاد می‌شود.


تصویر(11)

4. KeyError

KeyError مشابه IndexError است، اما به‌جای لیست یا تاپل، زمانی رخ می‌دهد که شما تلاش می‌کنید به یک کلید (key) که در دیکشنری وجود ندارد؛ دسترسی پیدا کنید.

در واقع می‌توانید آن را به‌عنوان IndexError برای دیکشنری‌ها تصور کنید.

در تصویر12 مثالی از بروز KeyError آورده شده است.


تصویر(12)

در این مثال، دیکشنری inventory شامل کلیدهایی مانند apple، banana و orange است. تلاش برای دسترسی به کلید grape که در دیکشنری وجود ندارد، باعث ایجاد KeyError مطابق تصویر13 می‌شود. 


تصویر(13)

5. NameError

NameError زمانی ایجاد می‌شود که شما به یک متغیر، ماژول، کلاس، تابع یا هر نام دیگری که در کد تعریف نشده است، ارجاعی انجام دهید.

درواقع NameError زمانی رخ می‌دهد که یک نام (name) استفاده‌شده در کد شما ناشناخته باشد، به این معنا که تعریف نشده یا خارج از دامنه قابل‌ دسترسی است.


تصویر(14)

در مثال تصویر14، متغیر x قبل از استفاده تعریف نشده است.

لذا تلاش برای انجام عملیات ریاضی با یک متغیر تعریف‌نشده، باعث بروز NameError مطابق تصویر15 می‌شود.


تصویر(15)

6. SyntaxError

SyntaxError زمانی رخ می‌دهد که سینتکس کد شما با قواعد زبان پایتون مطابقت نداشته باشد.

SyntaxError زمانی رخ می‌دهد که کد شما از نظر ساختاری اشتباه باشد و پایتون نتواند آن را تفسیر یا اجرا کند. این خطا معمولاً قبل از اجرای کد و در زمان تحلیل (parsing) شناسایی می‌شود.


تصویر(16)

در مثال تصویر16، پرانتز باز "(" در عبارت ریاضی 5 + 3 * 2 بسته نشده است.

این اشتباه در syntax باعث می‌شود پایتون نتواند کد را تحلیل کند و SyntaxError مطابق تصویر17 ایجاد شود.


تصویر(17)

7. TypeError

TypeError زمانی رخ می‌دهد که کد شما سعی کند عملیاتی را روی یک شیء انجام دهد که برای آن نوع شیء تعریف نشده است.

به طور مثال:

  • تلاش برای جمع‌کردن یک‌رشته با یک عدد صحیح

  • فراخوانی تابع len() روی شیئی که طول برای آن تعریف نشده است
در واقع TypeError زمانی ایجاد می‌شود که یک عملیات یا تابع برای یک نوع شیء خاص معتبر نباشد.


تصویر(18)

در مثال تصویر18، شما سعی کرده‌اید یک‌رشته ("5") را با یک عدد صحیح (5) جمع کنید.
این عملیات به دلیل ناسازگاری نوع داده‌ها باعث ایجاد TypeError مطابق تصویر19 می‌شود.


تصویر(19)

8. ValueError

ValueError زمانی رخ می‌دهد که مقدار یک شیء نادرست باشد.  این خطا مشابه IndexError است، اما به‌جای محدود بودن به مقادیر ایندکس، برای موارد کلی‌تری استفاده می‌شود.

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


تصویر(20)

در مثال تصویر20، تابع ()int سعی می‌کند رشته "hello" را به یک عدد صحیح تبدیل کند. از آنجایی‌که "hello" مقدار معتبری برای تبدیل به عدد نیست، مطابق تصویر21 ValueError رخ می‌دهد.


تصویر(21)

5/5 از 2 رای