Apa maksud penggunaan else
klausa opsional dari try
pernyataan itu?
Apa maksud penggunaan else
klausa opsional dari try
pernyataan itu?
Jawaban:
Pernyataan di else
blok dieksekusi jika eksekusi jatuh dari bagian bawah try
- jika tidak ada pengecualian. Jujur, saya tidak pernah menemukan kebutuhan.
Namun, Menangani Pengecualian mencatat:
Penggunaan klausa lain lebih baik daripada menambahkan kode tambahan ke klausa coba karena menghindari secara tidak sengaja menangkap pengecualian yang tidak dimunculkan oleh kode yang dilindungi oleh percobaan ... kecuali pernyataan.
Jadi, jika Anda memiliki metode yang dapat, misalnya, melempar IOError
, dan Anda ingin menangkap pengecualian yang dimunculkan, tetapi ada hal lain yang ingin Anda lakukan jika operasi pertama berhasil, dan Anda tidak ingin menangkap IOError dari operasi itu, Anda mungkin menulis sesuatu seperti ini:
try:
operation_that_can_throw_ioerror()
except IOError:
handle_the_exception_somehow()
else:
# we don't want to catch the IOError if it's raised
another_operation_that_can_throw_ioerror()
finally:
something_we_always_need_to_do()
Jika Anda hanya memasukkan another_operation_that_can_throw_ioerror()
setelah operation_that_can_throw_ioerror
, except
akan menangkap kesalahan panggilan kedua. Dan jika Anda meletakkannya setelah seluruh try
blok, itu akan selalu dijalankan, dan tidak sampai setelah finally
. The else
memungkinkan Anda memastikan
finally
blok, danIOError
ditimbulkannya tidak tertangkap di sinireturn
, continue
atau break
.
Ada satu alasan besar untuk menggunakan else
- gaya dan keterbacaan. Biasanya ide yang baik untuk menyimpan kode yang dapat menyebabkan pengecualian di dekat kode yang berhubungan dengannya. Sebagai contoh, bandingkan ini:
try:
from EasyDialogs import AskPassword
# 20 other lines
getpass = AskPassword
except ImportError:
getpass = default_getpass
dan
try:
from EasyDialogs import AskPassword
except ImportError:
getpass = default_getpass
else:
# 20 other lines
getpass = AskPassword
Yang kedua bagus ketika except
tidak bisa kembali lebih awal, atau melemparkan kembali pengecualian. Jika memungkinkan, saya akan menulis:
try:
from EasyDialogs import AskPassword
except ImportError:
getpass = default_getpass
return False # or throw Exception('something more descriptive')
# 20 other lines
getpass = AskPassword
Catatan: Jawaban disalin dari duplikat yang baru-baru ini diposting di sini , maka semua ini adalah "AskPassword".
Satu penggunaan: uji beberapa kode yang harus memunculkan pengecualian.
try:
this_should_raise_TypeError()
except TypeError:
pass
except:
assert False, "Raised the wrong exception type"
else:
assert False, "Didn't raise any exception"
(Kode ini harus diabstraksi menjadi tes yang lebih umum dalam praktiknya.)
Python coba lagi
Apa maksud penggunaan
else
klausa opsional dari pernyataan try?
Penggunaan yang dimaksudkan adalah memiliki konteks agar lebih banyak kode dapat dijalankan jika tidak ada pengecualian di mana kode itu diharapkan ditangani.
Konteks ini menghindari penanganan kesalahan yang tidak Anda harapkan.
Tapi penting untuk memahami kondisi yang tepat yang menyebabkan klausul lain untuk lari, karena return
, continue
dan break
dapat mengganggu aliran kontrol untuk else
.
The else
Pernyataan berjalan jika ada ada pengecualian dan jika tidak terganggu oleh return
, continue
atau break
pernyataan.
Opsional
else
klausul dijalankan jika dan ketika kontrol mengalir dari ujung daritry
klausa. *
(Huruf ditambahkan.) Dan catatan kaki berbunyi:
* Saat ini, kendali “mengalir dari ujung” kecuali dalam kasus pengecualian atau eksekusi dari
return
,continue
ataubreak
pernyataan.
Itu membutuhkan setidaknya satu sebelumnya kecuali klausa ( lihat tata bahasa ). Jadi itu sebenarnya bukan "coba-lagi," itu "coba-kecuali-lain (-akhirnya)," dengan else
(dan finally
) menjadi opsional.
The Python Tutorial mengelaborasi penggunaan yang dimaksudkan:
Coba ... kecuali pernyataan memiliki klausa opsional lain, yang, jika ada, harus mengikuti semua kecuali klausa. Ini berguna untuk kode yang harus dijalankan jika klausa coba tidak menimbulkan pengecualian. Sebagai contoh:
for arg in sys.argv[1:]: try: f = open(arg, 'r') except IOError: print 'cannot open', arg else: print arg, 'has', len(f.readlines()), 'lines' f.close()
Penggunaan klausa lain lebih baik daripada menambahkan kode tambahan ke klausa coba karena menghindari secara tidak sengaja menangkap pengecualian yang tidak dimunculkan oleh kode yang dilindungi oleh percobaan ... kecuali pernyataan.
else
versus kode mengikuti try
blokJika Anda menangani kesalahan, else
blok tidak akan berjalan. Sebagai contoh:
def handle_error():
try:
raise RuntimeError('oops!')
except RuntimeError as error:
print('handled a RuntimeError, no big deal.')
else:
print('if this prints, we had no error!') # won't print!
print('And now we have left the try block!') # will print!
Dan sekarang,
>>> handle_error()
handled a RuntimeError, no big deal.
And now we have left the try block!
Mencoba-kecuali-yang lain sangat bagus untuk menggabungkan pola EAFP dengan mengetik bebek :
try:
cs = x.cleanupSet
except AttributeError:
pass
else:
for v in cs:
v.cleanup()
Anda mungkin menganggap kode naif ini baik-baik saja:
try:
for v in x.cleanupSet:
v.clenaup()
except AttributeError:
pass
Ini adalah cara terbaik untuk menyembunyikan bug parah dalam kode Anda secara tidak sengaja. Saya mengetik pembersihan di sana, tetapi AttributeError yang akan memberi tahu saya sedang ditelan. Lebih buruk lagi, bagaimana jika saya menulisnya dengan benar, tetapi metode pembersihan kadang-kadang diteruskan tipe pengguna yang memiliki atribut salah nama, menyebabkannya gagal setengah jalan melalui dan meninggalkan file tidak tertutup? Semoga berhasil men-debug yang satu itu.
Saya merasa sangat berguna ketika Anda memiliki pembersihan untuk melakukan itu harus dilakukan bahkan jika ada pengecualian:
try:
data = something_that_can_go_wrong()
except Exception as e: # yes, I know that's a bad way to do it...
handle_exception(e)
else:
do_stuff(data)
finally:
clean_up()
Meskipun Anda tidak bisa memikirkan penggunaannya sekarang, Anda bisa bertaruh pasti ada gunanya. Berikut adalah contoh yang tidak imajinatif:
Dengan else
:
a = [1,2,3]
try:
something = a[2]
except:
print "out of bounds"
else:
print something
Tanpa else
:
try:
something = a[2]
except:
print "out of bounds"
if "something" in locals():
print something
Di sini Anda memiliki variabel yang something
ditentukan jika tidak ada kesalahan yang terjadi. Anda dapat menghapus ini di luar try
blok, tetapi kemudian memerlukan beberapa deteksi berantakan jika suatu variabel didefinisikan.
something = a[2]; print something
bagian dalam coba: blokir?
Ada contoh yang bagus try-else
dalam PEP 380 . Pada dasarnya, ia turun untuk melakukan penanganan pengecualian yang berbeda di berbagai bagian algoritma.
Ini sesuatu seperti ini:
try:
do_init_stuff()
except:
handle_init_suff_execption()
else:
try:
do_middle_stuff()
except:
handle_middle_stuff_exception()
Ini memungkinkan Anda untuk menulis kode penanganan pengecualian lebih dekat ke tempat pengecualian itu terjadi.
Dari Kesalahan dan Pengecualian # Menangani pengecualian - docs.python.org
The
try ... except
pernyataan memiliki opsionalelse
klausul, yang, ketika hadir, harus mengikuti semua kecuali klausa. Ini berguna untuk kode yang harus dijalankan jika klausa coba tidak menimbulkan pengecualian. Sebagai contoh:for arg in sys.argv[1:]: try: f = open(arg, 'r') except IOError: print 'cannot open', arg else: print arg, 'has', len(f.readlines()), 'lines' f.close()
Penggunaan klausa lain lebih baik daripada menambahkan kode tambahan ke klausa coba karena menghindari secara tidak sengaja menangkap pengecualian yang tidak dimunculkan oleh kode yang dilindungi oleh percobaan ... kecuali pernyataan.
Melihat referensi Python tampaknya else
dijalankan setelah try
ketika tidak ada pengecualian. Klausul opsional lain dijalankan jika dan ketika kontrol mengalir dari akhir klausa coba. 2 Pengecualian dalam klausa lain tidak ditangani oleh klausa sebelumnya kecuali.
Menyelam ke dalam python memiliki contoh di mana, jika saya mengerti dengan benar, dalam try
blok mereka mencoba mengimpor modul, ketika itu gagal Anda mendapatkan pengecualian dan mengikat default tetapi ketika berfungsi Anda memiliki pilihan untuk masuk ke else
blok dan mengikat apa yang diperlukan (lihat tautan untuk contoh dan penjelasan).
Jika Anda mencoba melakukan pekerjaan di catch
blok itu mungkin melemparkan pengecualian lain - saya kira di situlah else
blok berguna.
try
blok.
Itu dia. Blok 'lain' dari klausa coba-kecuali ada untuk kode yang berjalan ketika (dan hanya ketika) operasi yang dicoba berhasil. Itu bisa digunakan, dan bisa disalahgunakan.
try:
fp= open("configuration_file", "rb")
except EnvironmentError:
confdata= '' # it's ok if the file can't be opened
else:
confdata= fp.read()
fp.close()
# your code continues here
# working with (possibly empty) confdata
Secara pribadi, saya suka dan menggunakannya saat yang tepat. Secara semantik mengelompokkan pernyataan.
Mungkin penggunaannya mungkin:
#debug = []
def debuglog(text, obj=None):
" Simple little logger. "
try:
debug # does global exist?
except NameError:
pass # if not, don't even bother displaying
except:
print('Unknown cause. Debug debuglog().')
else:
# debug does exist.
# Now test if you want to log this debug message
# from caller "obj"
try:
if obj in debug:
print(text) # stdout
except TypeError:
print('The global "debug" flag should be an iterable.')
except:
print('Unknown cause. Debug debuglog().')
def myfunc():
debuglog('Made it to myfunc()', myfunc)
debug = [myfunc,]
myfunc()
Mungkin ini akan membawa Anda terlalu berguna.
Saya telah menemukan try: ... else:
konstruk yang berguna dalam situasi di mana Anda menjalankan kueri basis data dan mencatat hasil kueri tersebut ke basis data terpisah dengan rasa / jenis yang sama. Katakanlah saya memiliki banyak utas pekerja yang menangani semua kueri basis data yang dikirimkan ke antrian
#in a long running loop
try:
query = queue.get()
conn = connect_to_db(<main db>)
curs = conn.cursor()
try:
curs.execute("<some query on user input that may fail even if sanitized">)
except DBError:
logconn = connect_to_db(<logging db>)
logcurs = logconn.cursor()
logcurs.execute("<update in DB log with record of failed query")
logcurs.close()
logconn.close()
else:
#we can't put this in main try block because an error connecting
#to the logging DB would be indistinguishable from an error in
#the mainquery
#We can't put this after the whole try: except: finally: block
#because then we don't know if the query was successful or not
logconn = connect_to_db(<logging db>)
logcurs = logconn.cursor()
logcurs.execute("<update in DB log with record of successful query")
logcurs.close()
logconn.close()
#do something in response to successful query
except DBError:
#This DBError is because of a problem with the logging database, but
#we can't let that crash the whole thread over what might be a
#temporary network glitch
finally:
curs.close()
conn.close()
#other cleanup if necessary like telling the queue the task is finished
Tentu saja jika Anda dapat membedakan antara kemungkinan pengecualian yang mungkin dilemparkan, Anda tidak harus menggunakan ini, tetapi jika kode bereaksi terhadap potongan kode yang berhasil mungkin melemparkan pengecualian yang sama dengan bagian yang berhasil, dan Anda tidak bisa hanya biarkan pengecualian kedua yang mungkin pergi, atau segera kembali pada kesuksesan (yang akan mematikan utas dalam kasus saya), maka ini berguna.
Sebuah else
blok sering dapat eksis untuk fungsi yang terjadi di setiap except
blok.
try:
test_consistency(valuable_data)
except Except1:
inconsistency_type = 1
except Except2:
inconsistency_type = 2
except:
# Something else is wrong
raise
else:
inconsistency_type = 0
"""
Process each individual inconsistency down here instead of
inside the except blocks. Use 0 to mean no inconsistency.
"""
Dalam hal ini, inconsistency_type
disetel di setiap blok kecuali, sehingga perilaku dilengkapi dalam kasus no-error di else
.
Tentu saja, saya menggambarkan ini sebagai pola yang mungkin muncul dalam kode Anda sendiri suatu hari nanti. Dalam kasus khusus ini, Anda hanya menetapkan inconsistency_type
ke 0 sebelum try
blok.
Berikut adalah tempat lain di mana saya suka menggunakan pola ini:
while data in items:
try
data = json.loads(data)
except ValueError as e:
log error
else:
# work on the `data`
continue
saja - pola "break out early". Ini memungkinkan Anda untuk menjatuhkan klausa "lain" dan lekukannya, membuat kode lebih mudah dibaca.
Salah satu skenario penggunaan yang dapat saya pikirkan adalah pengecualian yang tidak dapat diprediksi, yang dapat dihindari jika Anda mencoba lagi. Misalnya, ketika operasi di blok uji coba melibatkan angka acak:
while True:
try:
r = random.random()
some_operation_that_fails_for_specific_r(r)
except Exception:
continue
else:
break
Tetapi jika pengecualian dapat diprediksi, Anda harus selalu memilih validasi terlebih dahulu daripada pengecualian. Namun, tidak semuanya dapat diprediksi, sehingga pola kode ini memiliki tempatnya.
break
dalam try
di bagian akhir, yang merupakan IMO bersih, dan Anda tidak memerlukannya else
. Juga continue
tidak benar-benar dibutuhkan, Anda bisa saja pass
.
Saya menemukan else
berguna untuk berurusan dengan file konfigurasi yang mungkin salah:
try:
value, unit = cfg['lock'].split()
except ValueError:
msg = 'lock monitoring config must consist of two words separated by white space'
self.log('warn', msg)
else:
# get on with lock monitoring if config is ok
Pengecualian yang membaca lock
konfigurasi menonaktifkan pemantauan kunci dan ValueErrors mencatat pesan peringatan yang bermanfaat.
Misalkan logika pemrograman Anda tergantung pada apakah kamus memiliki entri dengan kunci yang diberikan. Anda dapat menguji hasil dict.get(key)
menggunakan if... else...
konstruk, atau Anda dapat melakukan:
try:
val = dic[key]
except KeyError:
do_some_stuff()
else:
do_some_stuff_with_val(val)
Saya akan menambahkan use case lain yang tampaknya lurus ke depan saat menangani sesi DB:
# getting a DB connection
conn = db.engine.connect()
# and binding to a DB session
session = db.get_session(bind=conn)
try:
# we build the query to DB
q = session.query(MyTable).filter(MyTable.col1 == 'query_val')
# i.e retrieve one row
data_set = q.one_or_none()
# return results
return [{'col1': data_set.col1, 'col2': data_set.col2, ...}]
except:
# here we make sure to rollback the transaction,
# handy when we update stuff into DB
session.rollback()
raise
else:
# when no errors then we can commit DB changes
session.commit()
finally:
# and finally we can close the session
session.close()
The else:
blok membingungkan dan (hampir) tidak berguna. Itu juga bagian dari for
dan while
pernyataan.
Sebenarnya, bahkan pada- if
pernyataan, else:
dapat disalahgunakan dengan cara yang benar-benar mengerikan membuat bug yang sangat sulit ditemukan.
Pertimbangkan ini.
if a < 10:
# condition stated explicitly
elif a > 10 and b < 10:
# condition confusing but at least explicit
else:
# Exactly what is true here?
# Can be hard to reason out what condition is true
Pikirkan dua kali else:
. Ini umumnya masalah. Hindari kecuali dalam if
pernyataan-dan bahkan kemudian mempertimbangkan mendokumentasikan else
- kondisi untuk membuatnya eksplisit.
if x > 0: return "yes"
dan if x <= 0: return "no"
. Sekarang seseorang datang dan mengubah salah satu syarat untuk mengatakan x > 1
tetapi lupa untuk mengubah yang lain. Bagaimana itu mengurangi jumlah bug yang mau dilakukan. if else
klausa kadang-kadang banyak garis yang terpisah. KERING adalah praktik yang baik, jauh lebih sering daripada tidak, sungguh. (maaf untuk pos ganda).