التعامل مع الأخطاء أمر طبيعي لكل من يبدأ باستخدام بايثون أو حتى المبرمجين ذوي الخبرة. غالباً ما تظهر رسائل مربكة مثل SyntaxError أو IndentationError فتعيق تشغيل البرنامج وتستهلك الكثير من الوقت. معرفة أسباب هذه الأخطاء وكيفية إصلاحها بشكل صحيح يجعل عملية البرمجة أسرع وأكثر سلاسة. فهم المشكلة من جذورها هو الخطوة الأولى لتجنب تكرارها وتحسين أسلوب كتابة الشيفرة.
هناك أنواع عديدة من الأخطاء في بايثون. بغض النظر عن المرحلة التي وصلت إليها في تعلم بايثون، فمن المرجح أنك واجهتَ واحدًا أو أكثر من هذه الأخطاء. قد يكون من السهل على البعض معرفة الخطأ في الكود. أما بالنسبة للآخرين؟ ليس الأمر كذلك. لهذا السبب أشرح معناها.
5. خطأ المسافة البادئة
إذا كنت مبتدئًا تمامًا في بايثون أو انتقلت من لغة مثل C/C++ أو جافا، فسيكون هذا الخطأ الأكثر شيوعًا الذي ستواجهه. في بايثون، نُعرّف الكتل باستخدام المسافة البادئة بدلًا من الأقواس، كما هو شائع في العديد من اللغات الأخرى. تشير “الكتلة” إلى جزء من الكود يُعامل كوحدة واحدة. فكّر في الكتل الشرطية، أو الدالة، أو الحلقة التكرارية.
في بايثون، يجب أن يكون لجميع العبارات داخل الكتلة نفس مستوى المسافة البادئة. عندما يتغير مستوى المسافة البادئة (إما بالزيادة أو النقصان)، فإنه يُشير إلى بداية الكتلة أو نهايتها. تعتمد بايثون بشكل كبير على المسافة البادئة الثابتة. سيؤدي عدم تناسق المسافة البادئة إلى خطأ IndentationError.
من الحالات الشائعة التي قد تواجه فيها هذا الخطأ عند نسخ ولصق الكود في محرر النصوص. أحيانًا، بسبب اختلاف تنسيق النصوص بين مختلف المحررات، قد تنقطع المسافة البادئة من محرر لآخر.
for i in range(5):
print(i)
أثناء نسخ أسطر الكود أعلاه، انقطعت المسافة البادئة. سيؤدي تشغيل هذا الكود إلى حدوث خطأ في المسافة البادئة. لإصلاح هذا، يجب وضع مسافة بادئة متسقة للعبارات أسفل كتلتها.
for i in range(5):
print(i)
هناك مشكلة أخرى قد تواجهها تتعلق بهذا الخطأ، وهي استخدام علامات التبويب والمسافات. تستخدم بعض المحررات علامات التبويب، بينما يستخدم البعض الآخر أربع مسافات للمسافة البادئة. إذا خلطتَ بينهما في الكود، فستحصل على خطأ. هذا الخطأ أكثر إرباكًا لأنه من الصعب التمييز بالعين المجردة أي سطر يحتوي على علامات تبويب وأي سطر يحتوي على مسافات.
4. خطأ بناء الجملة
لكل لغة برمجة قواعد بناء جملة. بمعنى آخر، مجموعة من القواعد التي يجب اتباعها لكتابة الكود بتلك اللغة. لذلك، إذا خالفتَ أيًا من هذه القواعد، فلن تعرف اللغة ما تحاول فعله وستظهر لك خطأ بناء جملة.
في بايثون، يحدث خطأ بناء الجملة عندما يجد المترجم كودًا لا يتوافق مع قواعد لغة بايثون. هذا يعني أن الكود مُهيكل بطريقة لا تستطيع بايثون فهمها أو تنفيذها. سيمنع خطأ بناء الجملة برنامجك من البدء. من أكثر أخطاء بناء الجملة شيوعًا التي ستواجهها في بايثون:
عدم استخدام علامة ترقيم (مثل نسيان النقطتين (:) عند بدء كتلة برمجية، مثل الجمل الشرطية أو الحلقات التكرارية أو الدوال).
- الخطأ في تهجئة كلمة رئيسية في بايثون أو وضعها في مكان خاطئ (كتابة esle بدلًا من else، باستخدام جملة break حيث لا يُفترض ظهورها).
- استخدام كلمات رئيسية محجوزة كأسماء للمتغيرات.
- إساءة استخدام العوامل (مثل استخدام عامل الإسناد (=) بدلًا من عامل المساواة (==) في جملة).
- نسيان إنهاء قوس أو علامة اقتباس. يحدث هذا غالبًا عند العمل مع تعبيرات متعددة داخل أقواس متداخلة.
الخبر السار هو أن مُفسّر بايثون ذكي بما يكفي لتحديد نوع خطأ بناء الجملة الذي ارتكبته بدقة، والإشارة إلى رقم السطر، وحتى الموقع التقريبي للخطأ. مع ذلك، قد تكون رسالة الخطأ غامضة بعض الشيء في بعض الأحيان ولا تعكس السبب الدقيق. إذا كنت تستخدم محرر أكواد أو بيئة تطوير متكاملة جيدة، فيمكنه اقتراح الخطأ والحلول الممكنة.
3. خطأ الفهرس
يوفر بايثون العديد من هياكل البيانات المضمنة، مثل القوائم والمجموعات والمجموعات. غالبًا ما نحتاج إلى التكرار خلال هياكل البيانات هذه والوصول إلى العناصر. تحتوي كل بنية بيانات على ما يسمى بالفهرس، وهو موقع عنصر محدد في تلك البنية.
numbers = [1, 2, 3]
لدينا هنا قائمة أرقام. يُمكننا الوصول إلى عناصر القائمة من خلال فهارسها، كما يلي:
print(numbers[1]) # prints 2
يحدث خطأ IndexError عادةً عند محاولة الوصول إلى عنصر في بنية بيانات (تُسمى أيضًا تسلسلًا) بفهرس خارج نطاق الفهارس المسموح به لتلك البنية. في العديد من لغات البرمجة، بما في ذلك بايثون، يبدأ الفهرس من الصفر. لذا، إذا احتوى التسلسل على N عنصر، فإن نطاق الفهارس يتراوح بين 0 وN-1.
غالبًا ما ينسى المبرمجون التعامل مع حالة الفهرسة الصفرية هذه، فيقعون في خطأ الانحراف بواحد، مما يؤدي إلى خطأ في الفهرسة. لتجنب أخطاء الفهرسة، احرص دائمًا على قياس طول التسلسل.
if index < len(my_list):
# execute code
عند تكرار تسلسل، يُعد تعديله أيضًا خطأً شائعًا يقع فيه العديد من المبرمجين في بايثون. يُسبب هذا أيضًا خطأً في الفهرس. لذا، تجنب القيام بذلك.
2. خطأ القيمة
يوفر بايثون أنواعًا متعددة من البيانات. عند العمل مع أنواع بيانات مختلفة، نحتاج إلى التعامل مع قيم حرفية مختلفة. أحيانًا، نستخدمها كوسائط دالة. ما نحتاج إلى معرفته هو أن كل دالة لها نوع بيانات متوقع كمُعامل. عند استلام هذه البيانات، تتحقق الدالة أيضًا مما إذا كانت القيمة التي استلمتها صالحة.
وهذا يُؤدي إلى خطأ القيمة في بايثون. وهو استثناء مُدمج يُطلق عندما تستقبل دالة أو عملية مُعاملًا له نوع البيانات الصحيح ولكن بقيمة غير مناسبة. هذا يعني أن نوع المُعامل مقبول، لكن قيمته المُحددة غير صالحة للعملية التي يتم تنفيذها.
من الحالات الشائعة جدًا لهذا هو عندما تريد تحويل نوع بيانات إلى نوع آخر.
int('10')
يؤدي هذا إلى تحويل السلسلة ’10’ إلى العدد الصحيح 10. ولكن، إذا قمت بذلك:
int('ten')
ستحصل على خطأ في القيمة. ذلك لأن دالة int() تتوقع وسيطة من نوع بيانات سلسلة نصية. ولكن يجب أن تتكون هذه القيمة من أرقام. لهذا السبب، تُعتبر القيمة “عشرة” غير مقبولة. وبالمثل، قد تحصل على هذا الخطأ عند إجراء عمليات حسابية.
import math
math.sqrt(-5)
تتوقع دالة sqrt() رقمًا موجبًا. لذا، سيؤدي إدخال رقم سالب كوسيطة إلى خطأ في القيمة. ومن الحالات الشائعة الأخرى التي تواجه فيها أخطاء القيمة عند إدخال المستخدم. فنظرًا لعدم تحكمك فيما يُدخله المستخدم، فإن كتابة قيمة خاطئة سيؤدي إلى حدوث خطأ.
أفضل طريقة للتعامل مع خطأ القيمة هي استخدام كتل المحاولة باستثناء.
try:
num = input("Enter a number: ")
num_int = int(num)
except ValueError as e:
print(f"Caught a ValueError: {e}")
بهذه الطريقة، يمكنك منع تعطل البرنامج حتى لو أدخل المستخدم قيمة خاطئة.
1. AttributeError
يُعد خطأ السمة استثناءً شائعًا في بايثون، يحدث عند محاولة الوصول إلى سمة أو دالة غير موجودة في كائن معين. ببساطة، يعني ذلك أنك تطلب من الكائن القيام بشيء لم يُصمم له.
سواء كنت تعمل مع سلاسل نصية أو قوائم أو فئات مخصصة، فمن السهل افتراض أن الكائن يمتلك خصائص أو إمكانيات معينة، خاصةً عند التبديل بين أنواع بيانات مختلفة. ومع ذلك، سيُطلق بايثون خطأ السمة عند محاولة استدعاء سمة غير متوفرة.
text = "hello world"
print(text.push())
لا تحتوي السلاسل النصية على دالة push(). لذا، في المثال أعلاه، ستحصل على خطأ في السمة. إليك مثال آخر:
user = None
print(user.name)
سيؤدي أيضًا محاولة الوصول إلى سمة “الاسم” في كائن NoneType إلى ظهور هذا الخطأ. في جميع هذه الحالات، لا يدعم الكائن الذي تعمل عليه السمة التي تحاول الوصول إليها. لمنع هذا الخطأ من مقاطعة برنامجك، يُرجى التحقق من أنواع الكائنات.
type(obj) # or
isinstance()
تُظهر دالة dir() المدمجة جميع السمات والأساليب الصالحة المتاحة على الكائن. استخدامها على الكائن يُمكّنك من معرفة السمات التي يمكنك استخدامها.
بما أن بايثون لغة سهلة، فمن السهل جدًا تعلم أساسياتها. الآن، وبعد أن تعرفت على بعض الأخطاء الشائعة، ستتمكن من تصحيحها وكتابة المزيد من أكواد بايثون دون أي قلق.
مواجهة الأخطاء في بايثون ليست نهاية المطاف، بل فرصة لفهم اللغة بشكل أعمق وتحسين مهاراتك البرمجية. كل خطأ له تفسير وحل واضح بمجرد قراءة رسالة الخطأ بعناية وتجربة التعديلات المناسبة. بالتدريب المستمر ستصبح الأخطاء مجرد خطوات طبيعية في رحلة التعلم، مما يمنحك القدرة على كتابة أكواد أكثر استقراراً وكفاءة.