Apa alasan keberadaan try-kecuali-selain itu ada?
Sebuah try
blok memungkinkan Anda untuk menangani kesalahan yang diharapkan. The except
block hanya harus menangkap pengecualian Anda siap untuk menangani. Jika Anda menangani kesalahan yang tidak terduga, kode Anda mungkin melakukan hal yang salah dan menyembunyikan bug.
Sebuah else
klausa akan dieksekusi jika tidak ada kesalahan, dan dengan tidak mengeksekusi kode itu di try
blok, Anda menghindari menangkap kesalahan yang tidak terduga. Sekali lagi, menangkap kesalahan yang tidak terduga dapat menyembunyikan bug.
Contoh
Sebagai contoh:
try:
try_this(whatever)
except SomeException as the_exception:
handle(the_exception)
else:
return something
Suite "coba, kecuali" memiliki dua klausa opsional, else
dan finally
. Jadi sebenarnya try-except-else-finally
.
else
akan mengevaluasi hanya jika tidak ada pengecualian dari try
blok. Ini memungkinkan kami untuk menyederhanakan kode yang lebih rumit di bawah ini:
no_error = None
try:
try_this(whatever)
no_error = True
except SomeException as the_exception:
handle(the_exception)
if no_error:
return something
jadi jika kita membandingkan suatu else
dengan alternatif (yang mungkin membuat bug) kita melihat bahwa itu mengurangi garis-garis kode dan kita dapat memiliki basis kode yang lebih mudah dibaca, dirawat, dan kurang buggy.
finally
finally
akan mengeksekusi tidak peduli apa, bahkan jika baris lain sedang dievaluasi dengan pernyataan pengembalian.
Rusak dengan kode semu
Mungkin membantu untuk memecah ini, dalam bentuk sekecil mungkin yang menunjukkan semua fitur, dengan komentar. Anggap ini benar secara sintaksis (tetapi tidak bisa dijalankan kecuali nama-nama didefinisikan) pseudo-code dalam suatu fungsi.
Sebagai contoh:
try:
try_this(whatever)
except SomeException as the_exception:
handle_SomeException(the_exception)
# Handle a instance of SomeException or a subclass of it.
except Exception as the_exception:
generic_handle(the_exception)
# Handle any other exception that inherits from Exception
# - doesn't include GeneratorExit, KeyboardInterrupt, SystemExit
# Avoid bare `except:`
else: # there was no exception whatsoever
return something()
# if no exception, the "something()" gets evaluated,
# but the return will not be executed due to the return in the
# finally block below.
finally:
# this block will execute no matter what, even if no exception,
# after "something" is eval'd but before that value is returned
# but even if there is an exception.
# a return here will hijack the return functionality. e.g.:
return True # hijacks the return in the else clause above
Memang benar bahwa kita dapat memasukkan kode dalam else
blok di try
blok sebagai gantinya, di mana ia akan berjalan jika tidak ada pengecualian, tetapi bagaimana jika kode itu sendiri menimbulkan pengecualian dari jenis yang kita tangkap? Membiarkannya di try
blok akan menyembunyikan bug itu.
Kami ingin meminimalkan baris kode di try
blok untuk menghindari penangkapan pengecualian yang tidak kami harapkan, dengan prinsip bahwa jika kode kami gagal, kami ingin kode tersebut gagal dengan keras. Ini adalah praktik terbaik .
Ini adalah pemahaman saya bahwa pengecualian bukan kesalahan
Dalam Python, sebagian besar pengecualian adalah kesalahan.
Kita dapat melihat hierarki pengecualian dengan menggunakan pydoc. Misalnya, dalam Python 2:
$ python -m pydoc exceptions
atau Python 3:
$ python -m pydoc builtins
Akan memberi kita hierarki. Kita dapat melihat bahwa sebagian besar jenis Exception
kesalahan, meskipun Python menggunakan beberapa dari mereka untuk hal-hal seperti mengakhiri for
loop ( StopIteration
). Ini adalah hierarki Python 3:
BaseException
Exception
ArithmeticError
FloatingPointError
OverflowError
ZeroDivisionError
AssertionError
AttributeError
BufferError
EOFError
ImportError
ModuleNotFoundError
LookupError
IndexError
KeyError
MemoryError
NameError
UnboundLocalError
OSError
BlockingIOError
ChildProcessError
ConnectionError
BrokenPipeError
ConnectionAbortedError
ConnectionRefusedError
ConnectionResetError
FileExistsError
FileNotFoundError
InterruptedError
IsADirectoryError
NotADirectoryError
PermissionError
ProcessLookupError
TimeoutError
ReferenceError
RuntimeError
NotImplementedError
RecursionError
StopAsyncIteration
StopIteration
SyntaxError
IndentationError
TabError
SystemError
TypeError
ValueError
UnicodeError
UnicodeDecodeError
UnicodeEncodeError
UnicodeTranslateError
Warning
BytesWarning
DeprecationWarning
FutureWarning
ImportWarning
PendingDeprecationWarning
ResourceWarning
RuntimeWarning
SyntaxWarning
UnicodeWarning
UserWarning
GeneratorExit
KeyboardInterrupt
SystemExit
Seorang komentator bertanya:
Katakanlah Anda memiliki metode yang mem-ping API eksternal dan Anda ingin menangani pengecualian pada kelas di luar pembungkus API, apakah Anda hanya mengembalikan e dari metode di bawah klausa kecuali di mana e adalah objek pengecualian?
Tidak, Anda tidak mengembalikan pengecualian, hanya jalankan kembali dengan telanjang raise
untuk mempertahankan stacktrace.
try:
try_this(whatever)
except SomeException as the_exception:
handle(the_exception)
raise
Atau, dalam Python 3, Anda bisa menaikkan pengecualian baru dan mempertahankan backtrace dengan rantai pengecualian:
try:
try_this(whatever)
except SomeException as the_exception:
handle(the_exception)
raise DifferentException from the_exception
Saya menguraikan jawaban saya di sini .