Exceptions, Errors, WTF?
مش فى شئ كامل وطالما كتبت كود توقع انك هتلقة فيه مشكلات! مثلا انقطاع الإتصال مع الداتابيز او مشكلات فى النتورك او مكتبيات غير متوافرة او كود خاطئ SyntaxError او بيانات دخلها المستخدم بصورة خاطئة او خطئ رياضي او او
اولا ايه هى الexceptions ؟ هى شئ حصل يتسبب فى تغيير مسار برنامجك "اللى انت خططه"
المفتاح للموضوع دا 4 حاجات (مش شرط يكون خطأ) ولكن شئ غير محسوب
1- try
2- except
3- finally
4- raise
try مش فيها شئ عجيب كل المطلوب منك هو انك تضيف الجزء اللى هتشك ان ممكن يحصل فيه exception
except: بتصطاد فيها ال exception وتعالجه
finally : الكود المرتبط بيها هيتم تنفيذ دائما حتى لو مش عالجت ال exception بتكون غالبا لإغلاق الريسورسز المفتوحة (مثلا فايل او كونكشن معين)
raise: هى المسئولة عن اطلاق ال exceptions دى
تعالى نشرحها بمثال شهير جدا
هنحاول نقسم عدد على صفر
رد بايثون
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
1/0
ZeroDivisionError: integer division or modulo by zero
>>>
لاحظ السطر ZeroDivisionError: integer division or modulo by zero
بيتكلم فيه عن حدوث Error للقسمة على صفر + وصف الError
طب جميل جدا انا كدا عرفت ان ممكن يتقسم على صفر طب انا عايز اصطاد ان حد حاول يعمل كدا
1- حط الكود بتاعك فى try بلوك
2- هندل الexception فى except بلوك
try:
print 1/0
except ZeroDivisionError, e:
print e.message
#output: integer division or modulo by zero
مثال آخر ادخال قيم غير سليمة او منطقية
>>> def sayHi(name):
if not isinstance(name, str):
raise ValueError("name ain't string.")
else:
print "Hi, %s"%name
هنا عرفنا function بإسم sayHi بتاخد بارمتر واحد بإسم name (منطقيا لازم يكون str) وإلا مثلا مش هنقول hi لرقم!؟ فى حالة ان المستخدم هيباصى رقم او اى شئ غير str هنعمل raise لإيرور بإسم ValueError (معرف مسبقا) وبرسالة name ain't string
>>> sayHi(9)
Traceback (most recent call last):
File "<pyshell#27>", line 1, in <module>
sayHi(9)
File "<pyshell#26>", line 3, in sayHi
raise ValueError("name ain't string.")
ValueError: name ain't string.
تعالى نعمل مثال لإنشاء exception خاص بيك
عايزين نكتب فنكشن معينة تقرا رقم من المستخدم وتعمل بيه return لكن لو المستخدم دخل قيمة مخالفة يتم عملraise ل Exception بإسم IntOnly
1- انشئ الكلاس الجديد واشتقه من نوع Exception او Error مناسب
>>> class IntOnly(ValueError):
def __init__(self, msg):
self.message=msg
def __str__(self):
return repr(self.message)
2- اكتب الفنكشن واعمل raise للIntOnly فى حال عدم التوافق
>>> def readInt():
inp=raw_input("Enter a num: ")
try:
i=int(inp) #cast to integer.
return i
except Exception:
raise IntOnly("Integers only are allowed.")
3- اكتب كود برنامجك
>>> try:
j=readInt()
except IntOnly, e:
print e.message
هنا بنستدعى readInt ونسند قيمتها ل j فى ال try block
فى حالة حدوث ايرور من النوع IntOnly هنعمل منه اوبجكت (اللى هو e ) ونشوف e.message
ودا الأسلوب المفضل
تقدر تتعامل مع كذا اكسبشن بإستخدام except حسب ماتحب طالما الكود بتاعك فيه مشاكل
مثال على finally
#!/usr/bin/python
f = None #out of try block. As finally doesn't have try' context
try:
f = file('somefile, 'r')
lines = f.readlines()
for line in lines:
print line, #avoid \n\n !
except IOError, e:
print 'IOErrorError'
finally: #cleaning up
if f:
f.close()
كدا وصلنا للصيغة العامة
try:
suite
except EX1, ex1: suite
except EX2, ex2: suite
except EX3, ex3: suite
finally: suite
يوجد بعض الكلاسات المجهزة للتعامل مع الإستثناءات/الأخطاء
BaseException: هو الأب
Exception: هو الأب المشتق منه الإستثناءات المعتادة
ImportError: محاولة استدعاء موديل
KeyboardInterrupt: عندما يقاطع المستخدم التنفيذ (غالبا ب ^C)
NameError: محاولة استدعاء identifier غير موجود
SyntaxError: كود بايثون خاطئ
IndexError: الوصول لترتيب غير موجود فى sequence معينة
KeyError: مفتاح غير موجود فى قاموس معين
IOError: مشاكل فى الدخل او الخرج IO ملف غير موجود مثلا
OverflowError: تعدى الحجم المسموح بيه لنوع معين
OSError: نظام التشغيل
AssertionError: خطأ نتج بسبب فشل فى assert expression
>>> 1==0
False
>>> assert 1==0
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
assert 1==0
AssertionError
أكتب اكواد افضل وعالجها بصورة افضل!