Perbedaan antara kecuali: dan kecuali Exception as e: dengan Python

147

Kedua potongan kode berikut melakukan hal yang sama. Mereka menangkap setiap pengecualian dan mengeksekusi kode di except:blok tersebut

Cuplikan 1 -

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

Cuplikan 2 -

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

Apa sebenarnya perbedaan di kedua konstruksi tersebut?

narendranathjoshi
sumber
7
@ user2725093 itu bukan pertanyaan yang sama. Orang yang Anda tautkan menanyakan apa perbedaan antara except Exception, e:dan except Exception as e:. Pertanyaan ini menanyakan apa perbedaan antara except:dan except Exception as e:.
Dennis

Jawaban:

167

Yang kedua Anda dapat mengakses atribut objek pengecualian:

>>> 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",)

Tapi itu tidak menangkap BaseExceptionatau pengecualian sistem SystemExit, KeyboardInterruptdan 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

Yang telanjang kecuali tidak:

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

Lihat bagian Pengecualian Bawaan dari dokumen dan bagian Kesalahan dan Pengecualian dari tutorial untuk info lebih lanjut.

agf
sumber
24
Tidak ada keajaiban di sini. Exceptionberasal dari BaseException, itulah mengapa except Exceptiontidak menangkap BaseException. Jika Anda menulis except BaseException, itu akan ketahuan juga. Bare exceptmenangkap semuanya.
fjarri
2
Saya harus menunjukkan bahwa telanjang exceptharus menjadi yang terakhir dalam serangkaian exceptblok, sementara Anda tidak akan mendapatkan kesalahan jika Anda meletakkan except Exceptionsebelum exceptblok lain : mereka hanya akan diabaikan secara diam-diam (jika mereka menangani Exceptionsubclass). Sesuatu yang harus diperhatikan.
Vanessa Phipps
@MatthewPhipps Itulah intinya, bukan? seperti pernyataan kasus atau blok if-else, eksekusi melompat ke kondisi pertama yang cocok ...
Dasar
1
@Basic Hanya menunjukkan perbedaan lain antara bare exceptdan except Exception. "Sesuatu yang harus diperhatikan" terlihat sedikit aneh sekarang, tetapi pada saat itu saya mengharapkan Python untuk memilih exceptblok yang paling spesifik , dimanapun itu, dan sedikit kecewa untuk mengetahui sebaliknya.
Vanessa Phipps
Perlu juga dicatat bahwa formulir kedua hanya boleh digunakan jika Anda tidak peduli tentang pengecualian itu atau ingin menanganinya dengan cara yang berarti.
Josh J
56
except:

menerima semua pengecualian, sedangkan

except Exception as e:

hanya menerima pengecualian yang seharusnya Anda tangkap.

Inilah contoh salah satu yang tidak seharusnya Anda tangkap:

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

Yang pertama membungkam KeyboardInterrupt!

Berikut daftar singkatnya:

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


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


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

Jika Anda ingin menangkap salah satu dari itu, yang terbaik adalah melakukannya

except BaseException:

untuk menunjukkan bahwa Anda tahu apa yang Anda lakukan.


Semua pengecualian berasal BaseException, dan pengecualian yang seharusnya Anda tangkap sehari-hari (yang akan diberikan untuk programmer) juga mewarisi Exception.

Veedrac
sumber
except(Exception)tidak pernah menemukan KeyboardInterruptkesalahan. as etidak ada hubungannya dengan itu.
pandita
2
Saya tidak pernah mengatakan itu. Saya belum pernah menyebutkannya as e, karena saya berasumsi sudah jelas apa yang dilakukannya.
Veedrac
2
Apakah ada kasus di mana seseorang akan menangkap BaseException DAN tahu apa yang mereka lakukan?
Davos
2
@Davos Ya, Anda mungkin lebih suka saat melakukan pembuatan log sementara, atau jika Anda menawarkan konsol kepada pengguna yang Anda tidak ingin pengecualian SystemExitatau KeyboardInterrupthindari. Bukan kasus umum, tetapi itu terjadi.
Veedrac
14

Ada perbedaan dengan beberapa pengecualian, misalnya KeyboardInterrupt.

Membaca PEP8 :

A bare exception: clause akan menangkap pengecualian SystemExit dan KeyboardInterrupt, membuatnya lebih sulit untuk mengganggu program dengan Control-C, dan dapat menyamarkan masalah lain. Jika Anda ingin menangkap semua pengecualian yang menandakan kesalahan program, gunakan pengecualian: (tanpa pengecualian sama dengan kecuali BaseException :).

Diego Herranz
sumber
3

Menggunakan formulir kedua memberi Anda variabel (dinamai berdasarkan asklausa, dalam contoh Anda e) dalam exceptlingkup blok dengan objek pengecualian terikat padanya sehingga Anda dapat menggunakan informasi dalam pengecualian (jenis, pesan, jejak tumpukan, dll) untuk menangani pengecualian di manor yang lebih dirancang khusus.

Silas Ray
sumber
1

Cara lain untuk melihat ini. Lihat detail pengecualian:

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']

Ada banyak "hal" untuk diakses menggunakan sintaks 'sebagai e'.

Kode ini hanya dimaksudkan untuk menunjukkan detail dari instance ini.

jouell
sumber