ความแตกต่างระหว่าง except: และ except Exception as e: in Python


148

ตัวอย่างโค้ดทั้งสองต่อไปนี้ทำสิ่งเดียวกัน พวกเขาจับทุกข้อยกเว้นและรันโค้ดในexcept:บล็อก

ตัวอย่างข้อมูล 1 -

try:
    #some code that may throw an exception
except:
    #exception handling code

ตัวอย่างข้อมูล 2 -

try:
    #some code that may throw an exception
except Exception as e:
    #exception handling code

อะไรคือความแตกต่างในโครงสร้างทั้งสอง?


7
@ user2725093 นั่นไม่ใช่คำถามเดียวกัน หนึ่งคุณเชื่อมโยงไปยังถามว่าความแตกต่างระหว่างและexcept Exception, e: except Exception as e:คำถามนี้ถามว่าสิ่งที่แตกต่างระหว่างและexcept: except Exception as e:
Dennis

คำตอบ:


167

ในวินาทีที่คุณสามารถเข้าถึงแอตทริบิวต์ของวัตถุข้อยกเว้น:

>>> def catch():
...     try:
...         asd()
...     except Exception as e:
...         print e.message, e.args
... 
>>> catch()
global name 'asd' is not defined ("global name 'asd' is not defined",)

แต่ก็ไม่ได้จับBaseExceptionหรือข้อยกเว้นระบบออกSystemExit, KeyboardInterruptและGeneratorExit:

>>> def catch():
...     try:
...         raise BaseException()
...     except Exception as e:
...         print e.message, e.args
... 
>>> catch()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in catch
BaseException

สิ่งที่ยกเว้นไม่:

>>> def catch():
...     try:
...         raise BaseException()
...     except:
...         pass
... 
>>> catch()
>>> 

ดูส่วนข้อยกเว้นในตัวของเอกสารและส่วนข้อผิดพลาดและข้อยกเว้นของบทช่วยสอนสำหรับข้อมูลเพิ่มเติม


24
ที่นี่ไม่มีเวทมนตร์ Exceptionที่ได้มาจากBaseExceptionที่ว่าทำไมไม่จับexcept Exception BaseExceptionถ้าเขียนexcept BaseExceptionก็โดนจับเหมือนกัน เปลือยexceptเพียงจับทุกอย่าง
fjarri

2
ฉันควรชี้ให้เห็นว่าการเปลือยexceptจะต้องอยู่ในชุดของexceptบล็อกในขณะที่คุณจะไม่ได้รับข้อผิดพลาดหากคุณวางไว้except Exceptionก่อนexceptบล็อกอื่น: พวกเขาจะถูกเพิกเฉยโดยไม่โต้ตอบ (หากจัดการExceptionคลาสย่อย) สิ่งที่ต้องระวัง
Vanessa Phipps

@MatthewPhipps นั่นคือประเด็นใช่มั้ย? เช่นกรณีคำสั่งหรือบล็อก if-else การดำเนินการจะข้ามไปยังเงื่อนไขแรกที่ตรงกับ ...
พื้นฐาน

1
@ พื้นฐานเพียงแค่ชี้ให้เห็นความแตกต่างระหว่างเปล่าexceptและexcept Exception. "สิ่งที่ต้องระวัง" ตอนนี้ดูแปลก ๆ ไปหน่อย แต่ในตอนนั้นฉันคาดว่า Python จะเลือกexceptบล็อกที่เฉพาะเจาะจงที่สุดไม่ว่าจะอยู่ที่ใดก็ตามและรู้สึกผิดหวังเล็กน้อยที่พบว่าเป็นอย่างอื่น
Vanessa Phipps

นอกจากนี้ยังเป็นที่น่าสังเกตว่าควรใช้รูปแบบที่สองก็ต่อเมื่อคุณไม่สนใจว่าข้อยกเว้นคืออะไรหรือต้องการจัดการอย่างมีความหมาย
Josh J

56
except:

ยอมรับข้อยกเว้นทั้งหมดในขณะที่

except Exception as e:

ยอมรับเฉพาะข้อยกเว้นที่คุณตั้งใจจะจับ

นี่คือตัวอย่างของสิ่งที่คุณไม่ได้ตั้งใจจะจับ:

>>> try:
...     input()
... except:
...     pass
... 
>>> try:
...     input()
... except Exception as e:
...     pass
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt

คนแรกเงียบKeyboardInterrupt!

นี่คือรายการด่วน:

issubclass(BaseException, BaseException)
#>>> True
issubclass(BaseException, Exception)
#>>> False


issubclass(KeyboardInterrupt, BaseException)
#>>> True
issubclass(KeyboardInterrupt, Exception)
#>>> False


issubclass(SystemExit, BaseException)
#>>> True
issubclass(SystemExit, Exception)
#>>> False

หากคุณต้องการจับสิ่งเหล่านี้ควรทำ

except BaseException:

เพื่อชี้ให้เห็นว่าคุณรู้ว่าคุณกำลังทำอะไรอยู่


ข้อยกเว้นทั้งหมดเกิดจากBaseExceptionและสิ่งที่คุณตั้งใจจะจับแบบวันต่อวัน (สิ่งที่จะถูกโยนให้โปรแกรมเมอร์) ก็รับมรดกเช่นExceptionกัน


except(Exception)ไม่เคยจับKeyboardInterruptข้อผิดพลาด as eไม่มีส่วนเกี่ยวข้องกับมัน
pandita

2
ฉันไม่เคยบอกว่ามันทำ ฉันไม่เคยพูดถึงเรื่องas eนี้เลยเพราะฉันคิดว่ามันชัดเจนว่ามันทำอะไร
Veedrac

2
มีกรณีใดบ้างที่บุคคลจะจับ BaseException และรู้ว่าพวกเขากำลังทำอะไรอยู่?
Davos

2
@Davos ใช่คุณอาจชอบเมื่อทำการบันทึกชั่วคราวหรือถ้าคุณเสนอคอนโซลให้กับผู้ใช้ที่คุณไม่ต้องการข้อยกเว้นเช่นSystemExitหรือKeyboardInterruptหลบหนี ไม่ใช่กรณีทั่วไป แต่จะเกิดขึ้น
Veedrac

14

มีข้อแตกต่างกับข้อยกเว้นบางประการเช่น KeyboardInterrupt

อ่านPEP8 :

ข้อยกเว้นเปล่า: อนุประโยคจะตรวจจับข้อยกเว้น SystemExit และ KeyboardInterrupt ทำให้ขัดขวางโปรแกรมด้วย Control-C ได้ยากขึ้นและสามารถปกปิดปัญหาอื่น ๆ หากคุณต้องการตรวจจับข้อยกเว้นทั้งหมดที่แสดงข้อผิดพลาดของโปรแกรมให้ใช้ข้อยกเว้น Exception: (bare except เทียบเท่ากับยกเว้น BaseException :)


3

การใช้รูปแบบที่สองจะทำให้คุณมีตัวแปร (ตั้งชื่อตามส่วนasคำสั่งในตัวอย่างของคุณe) ในexceptขอบเขตบล็อกโดยมีอ็อบเจ็กต์ข้อยกเว้นที่ผูกไว้เพื่อให้คุณสามารถใช้ข้อมูลในข้อยกเว้น (ประเภทข้อความการติดตามสแต็ก ฯลฯ ) เพื่อ จัดการข้อยกเว้นในคฤหาสน์ที่ปรับแต่งเป็นพิเศษมากขึ้น


1

อีกวิธีหนึ่งในการดูสิ่งนี้ ตรวจสอบรายละเอียดของข้อยกเว้น:

In [49]: try: 
    ...:     open('file.DNE.txt') 
    ...: except Exception as  e: 
    ...:     print(dir(e)) 
    ...:                                                                                                                                    
['__cause__', '__class__', '__context__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__suppress_context__', '__traceback__', 'args', 'characters_written', 'errno', 'filename', 'filename2', 'strerror', 'with_traceback']

มี "สิ่งต่างๆ" มากมายในการเข้าถึงโดยใช้ไวยากรณ์ "as e"

รหัสนี้มีไว้เพื่อแสดงรายละเอียดของอินสแตนซ์นี้เท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.