Sayangnya, saya tidak tahu cara menangani pengecualian untuk pernyataan python 'with'. Jika saya punya kode:
with open("a.txt") as f:
print f.readlines()
Saya benar-benar ingin menangani 'file not found exception' untuk melakukan sesuatu. Tetapi saya tidak bisa menulis
with open("a.txt") as f:
print f.readlines()
except:
print 'oops'
dan tidak bisa menulis
with open("a.txt") as f:
print f.readlines()
else:
print 'oops'
melampirkan 'dengan' dalam percobaan / kecuali pernyataan tidak berfungsi: pengecualian tidak dimunculkan. Apa yang bisa saya lakukan untuk memproses kegagalan di dalam pernyataan 'with' dengan cara Pythonic?
python
exception-handling
grigoryvp
sumber
sumber
with
pernyataan tidak ajaib istirahat sekitarnyatry...except
pernyataan.Jawaban:
Jika Anda ingin penanganan berbeda untuk kesalahan dari panggilan terbuka vs kode kerja yang dapat Anda lakukan:
sumber
try...except
blok tambahan di dalamwith
agar lebih dekat ke sumber pengecualian yang tidak ada hubungannya denganopen()
.Cara "Pythonic" terbaik untuk melakukan ini, mengeksploitasi
with
pernyataan, terdaftar sebagai Contoh # 6 dalam PEP 343 , yang memberikan latar belakang pernyataan tersebut.Digunakan sebagai berikut:
sumber
try...except
pernyataan.Pernyataan with telah tersedia tanpa
__future__
impor sejak Python 2.6 . Anda bisa mendapatkannya sedini Python 2.5 (tetapi pada titik ini saatnya untuk meningkatkan!) Dengan:Inilah hal terdekat untuk memperbaiki yang Anda miliki. Anda hampir sampai, tetapi
with
tidak memilikiexcept
klausa:Metode manajer konteks
__exit__
, jika dikembalikanFalse
akan membangkitkan kembali kesalahan ketika selesai. Jika kembaliTrue
, itu akan menekannya. Theopen
builtin ini__exit__
tidak kembaliTrue
, sehingga Anda hanya perlu sarang dalam mencoba, kecuali blok:Dan standar boilerplate: jangan gunakan yang telanjang
except:
yang menangkapBaseException
dan setiap kemungkinan pengecualian dan peringatan lainnya. Paling tidak sespesifikException
, dan untuk kesalahan ini, mungkin menangkapIOError
. Hanya menangkap kesalahan yang siap Anda tangani.Jadi dalam hal ini, Anda harus:
sumber
Membedakan antara kemungkinan asal-usul pengecualian yang muncul dari
with
pernyataan majemukMembedakan antara pengecualian yang terjadi dalam
with
pernyataan itu rumit karena mereka bisa berasal dari tempat yang berbeda. Pengecualian dapat diajukan dari salah satu tempat berikut (atau fungsi yang disebut di dalamnya):ContextManager.__init__
ContextManager.__enter__
with
ContextManager.__exit__
Untuk lebih jelasnya lihat dokumentasi tentang Jenis-jenis Manajer Konteks .
Jika kita ingin membedakan antara kasus-kasus yang berbeda, hanya membungkus
with
menjaditry .. except
tidak cukup. Pertimbangkan contoh berikut (menggunakanValueError
sebagai contoh tetapi tentu saja itu bisa diganti dengan jenis pengecualian lainnya):Di sini surat
except
wasiat akan menangkap pengecualian yang berasal dari keempat tempat yang berbeda dan karenanya tidak memungkinkan untuk membedakan di antara mereka. Jika kita memindahkan instantiasi objek manajer konteks di luarwith
, kita dapat membedakan antara__init__
danBLOCK / __enter__ / __exit__
:Secara efektif ini hanya membantu
__init__
bagian tetapi kita dapat menambahkan variabel sentinel tambahan untuk memeriksa apakah tubuh yangwith
mulai dieksekusi (yaitu membedakan antara__enter__
dan yang lain):Bagian yang sulit adalah untuk membedakan antara pengecualian yang berasal dari
BLOCK
dan__exit__
karena pengecualian yang lolos dari tubuhwith
akan diteruskan ke__exit__
yang dapat memutuskan bagaimana menanganinya (lihat dokumen ). Namun jika__exit__
memunculkan sendiri, pengecualian asli akan digantikan oleh yang baru. Untuk menangani kasus-kasus ini kita dapat menambahkanexcept
klausa umum dalam tubuhwith
untuk menyimpan setiap pengecualian potensial yang seharusnya lolos tanpa diketahui dan membandingkannya dengan yang tertangkap di terluarexcept
nanti - jika mereka sama, ini berarti asal usulnya.BLOCK
atau sebaliknya__exit__
(dalam kasus__exit__
menekan pengecualian dengan mengembalikan nilai sebenarnya yang paling luarexcept
tidak akan dieksekusi).Pendekatan alternatif menggunakan formulir setara yang disebutkan dalam PEP 343
PEP 343 - Pernyataan "with" menentukan versi
with
pernyataan "non-with" yang setara . Di sini kita dapat dengan mudah membungkus berbagai bagian dengantry ... except
dan dengan demikian membedakan antara sumber kesalahan potensial yang berbeda:Biasanya pendekatan yang lebih sederhana akan baik-baik saja
Kebutuhan untuk penanganan pengecualian khusus semacam itu harus sangat jarang dan biasanya membungkus keseluruhan
with
dalam satutry ... except
blok sudah cukup. Terutama jika berbagai sumber kesalahan ditunjukkan oleh tipe pengecualian (khusus) yang berbeda (manajer konteks perlu dirancang sesuai) kita dapat dengan mudah membedakannya. Sebagai contoh:sumber