จะรับชื่อข้อยกเว้นที่ติดใน Python ได้อย่างไร?


122

ฉันจะได้รับชื่อของข้อยกเว้นที่เพิ่มขึ้นใน Python ได้อย่างไร

เช่น,

try:
    foo = bar
except Exception as exception:
    name_of_exception = ???
    assert name_of_exception == 'NameError'
    print "Failed with exception [%s]" % name_of_exception

ตัวอย่างเช่นฉันพบข้อยกเว้นหลายรายการ (หรือทั้งหมด) และต้องการพิมพ์ชื่อของข้อยกเว้นในข้อความแสดงข้อผิดพลาด


3
ทำไมคุณถึงคิดว่าคุณต้องการสิ่งนี้? ทำไมไม่จับข้อยกเว้นที่เป็นรูปธรรมมากขึ้น (เช่นexcept NameError:) เพื่อเริ่มต้นด้วย?

7
ฉันมีสองสถานการณ์ที่ฉันต้องการตรวจจับข้อยกเว้นทั้งหมด (หรือรายการของข้อยกเว้น) และต้องการพิมพ์ชื่อของข้อยกเว้นในข้อความแสดงข้อผิดพลาด
Rob Bednark

1
คุณอาจต้องการตรวจสอบtracebackโมดูลของไลบรารีมาตรฐานซึ่งมีฟังก์ชันที่จัดรูปแบบข้อยกเว้นและการย้อนกลับได้ดี
Blckknght

1
@delnan สถานการณ์นี้เกิดขึ้นเมื่อคุณกำลังทดสอบว่าฟังก์ชันเพิ่มข้อยกเว้นตามที่ตั้งโปรแกรมไว้หรือไม่
gokul_uf

ฉันต้องการบางอย่างเช่นนี้เพื่อทำให้โค้ดแห้ง: วิธีการที่ฉันเรียกใช้มีข้อยกเว้นหลายประการซึ่งแต่ละข้อได้รับการจัดการด้วยexceptคำสั่งของตัวเองแต่รายการบันทึกจะคล้ายกันมากในแต่ละกรณี
Adam Carroll

คำตอบ:


226

วิธีต่างๆในการรับชื่อคลาสของข้อยกเว้นมีดังนี้

  1. type(exception).__name__
  2. exception.__class__.__name__
  3. exception.__class__.__qualname__

เช่น,

try:
    foo = bar
except Exception as exception:
    assert type(exception).__name__ == 'NameError'
    assert exception.__class__.__name__ == 'NameError'
    assert exception.__class__.__qualname__ == 'NameError'

6

วิธีนี้ได้ผล แต่ดูเหมือนว่าจะต้องมีวิธีที่ง่ายและตรงกว่านี้

try:
    foo = bar
except Exception as exception:
    assert repr(exception) == '''NameError("name 'bar' is not defined",)'''
    name = repr(exception).split('(')[0]
    assert name == 'NameError'

4
แทนที่กับชนิดของข้อยกเว้นที่คุณต้องการที่จะจับคือexcept Exception as exception except NameError as exception
Maciej Gol

8
ฉันไม่ต้องการจับข้อยกเว้นบางอย่างที่รู้ล่วงหน้า ฉันต้องการจับข้อยกเว้นทั้งหมด
Rob Bednark


1

หากคุณต้องการชื่อคลาสที่มีคุณสมบัติครบถ้วน (เช่นsqlalchemy.exc.IntegrityErrorแทนที่จะเป็นเพียงIntegrityError) คุณสามารถใช้ฟังก์ชันด้านล่างซึ่งฉันได้มาจากคำตอบที่ยอดเยี่ยมของ MB สำหรับคำถามอื่น (ฉันเพิ่งเปลี่ยนชื่อตัวแปรบางตัวเพื่อให้เหมาะกับรสนิยมของฉัน):

def get_full_class_name(obj):
    module = obj.__class__.__module__
    if module is None or module == str.__class__.__module__:
        return obj.__class__.__name__
    return module + '.' + obj.__class__.__name__

ตัวอย่าง:

try:
    # <do something with sqlalchemy that angers the database>
except sqlalchemy.exc.SQLAlchemyError as e:
    print(get_full_class_name(e))

# sqlalchemy.exc.IntegrityError

1

คำตอบอื่น ๆ ที่นี่เหมาะสำหรับวัตถุประสงค์ในการสำรวจ แต่ถ้าเป้าหมายหลักคือการบันทึกข้อยกเว้น (รวมถึงชื่อของข้อยกเว้น) อาจพิจารณาใช้logging.exceptionแทนการพิมพ์?

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