إعادة طرح استثناء بايثون.الذي للقبض؟
سؤال
أنا أتعلم استخدام بايثون.لقد عثرت للتو على هذا المقال:http://nedbatchelder.com/blog/200711/rethrowing_exceptions_in_python.htmlويصف إعادة الاستثناءات في بيثون، مثل هذا:
try:
do_something_dangerous()
except:
do_something_to_apologize()
raise
وبما أنك قمت بإعادة طرح الاستثناء، فيجب أن تكون هناك عبارة "استثناء خارجي".ولكن الآن، كنت أفكر.ماذا لو أن do_something_to_apologize() داخل باستثناء يلقي خطأ.أي واحد سيتم القبض عليه في "الصيد باستثناء" الخارجي؟الشخص الذي تعيد رميه أو الذي ألقيته بواسطة do_something_to_apologize() ؟أم هل سيتم اكتشاف الاستثناء ذي الأولوية القصوى أولاً؟
المحلول
جربه وانظر:
def failure():
raise ValueError, "Real error"
def apologize():
raise TypeError, "Apology error"
try:
failure()
except ValueError:
apologize()
raise
النتائج:
Traceback (most recent call last):
File "<pyshell#14>", line 10, in <module>
apologize()
File "<pyshell#14>", line 5, in apologize
raise TypeError, "Apology error"
TypeError: Apology error
السبب:تم بالفعل اكتشاف الخطأ "الحقيقي" من الوظيفة الأصلية بواسطة except
. apologize
يثير خطأ جديدا قبل raise
تم التوصل إليه.لذلك، raise
في ال except
لا يتم تنفيذ البند مطلقًا، ولا ينتشر سوى خطأ الاعتذار إلى الأعلى.لو apologize
يثير خطأً، فليس لدى بايثون أي طريقة لمعرفة أنك ستثير استثناءً مختلفًا بعد ذلك apologize
.
لاحظ أنه في بايثون 3، سيتم ذكر التتبع كلاهما الاستثناءات، مع رسالة توضح كيفية ظهور الاستثناء الثاني:
Traceback (most recent call last):
File "./prog.py", line 9, in <module>
File "./prog.py", line 2, in failure
ValueError: Real error
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "./prog.py", line 11, in <module>
File "./prog.py", line 5, in apologize
TypeError: Apology error
ومع ذلك، فإن الاستثناء الثاني (استثناء "الاعتذار") لا يزال هو الوحيد الذي ينتشر إلى الخارج ويمكن اكتشافه من قبل مستوى أعلى. except
بند.تم ذكر الاستثناء الأصلي في التتبع ولكنه تم تضمينه في الاستثناء اللاحق ولم يعد من الممكن اكتشافه.
نصائح أخرى
الاستثناء الذي يتم إلقاؤه بواسطة do_something_to_apologize ().لن يتم تشغيل الخط الذي يحتوي على RAVE أبدا، بسبب الاستثناء الذي ألقيته بواسطة do_something_to_apologize.أيضا، لا أعتقد أن هناك أي فكرة عن "الأولوية" في استثناءات بيثون.