Python kullanımı


197

Python ile raiseve raise fromarasındaki fark nedir ?

try:
    raise ValueError
except Exception as e:
    raise IndexError

hangi sonuç verir

Traceback (most recent call last):
  File "tmp.py", line 2, in <module>
    raise ValueError
ValueError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "tmp.py", line 4, in <module>
    raise IndexError
IndexError

ve

try:
    raise ValueError
except Exception as e:
    raise IndexError from e

hangi sonuç verir

Traceback (most recent call last):
  File "tmp.py", line 2, in <module>
    raise ValueError
ValueError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "tmp.py", line 4, in <module>
    raise IndexError from e
IndexError

9
PEP-3134'ü okudunuz mu?
jonrsharpe

4
Şimdi kullan raise IndexError from Nonedeyin.
Martijn Pieters

11
Heh. değil raise IndexError from Falsea yükseltir . Günümü şenlendirdin. TypeErrorIndexError
Mad Physicist


Bundan bahsetmek için doğru yer olup olmadığından emin değilim, ama Spyder kullanan herkese: Bu yapının tamamı orada çalışmıyor. 3 yılı aşkın bir süredir sorun ( github.com/spyder-ide/spyder/issues/2943 ), ancak zincirleme istisnalara gerek olmadığını düşünüyorlar.
Emil Bode

Yanıtlar:


230

Fark kullandığınızda olmasıdır from, __cause__nitelik ayarlanır ve mesaj istisna edildiğini bildiren doğrudan kaynaklanır . Eğer fromo zaman hayır __cause__ayarlanmışsa atlarsanız , ancak __context__öznitelik de ayarlanmış olabilir ve geri izleme, başka bir şeyle uğraşırken bağlamı gösterir .

Ayar __context__kullandığınız olur raisebir özel durum işleyici; raisebaşka bir yerde kullandıysanız __context__, hayır da ayarlanmış demektir.

A __cause__ayarlanırsa, __suppress_context__ = Trueistisnada bir bayrak da ayarlanır; zaman __suppress_context__olarak ayarlandığında True, __context__bir Traceback basarken göz ardı edilir.

Eğer bir istisna işleyicisinden yükseltirken yok bağlamını göstermek istiyorum (bir istemiyoruz başka istisna oldu taşıma sırasında , daha sonra kullanmak mesaj) raise ... from Nonekümesine __suppress_context__için True.

Başka bir deyişle, Python istisnalar üzerine bir bağlam belirler, böylece bir istisnanın nerede ortaya çıktığını gözlemleyebilir ve bunun yerine başka bir istisnanın yerini alıp almadığınızı görebilirsiniz. Ayrıca , bir istisnanın nedenini ekleyerek izlemeyi diğer istisna hakkında açık hale getirebilirsiniz (farklı ifadeler kullanın) ve bağlam yok sayılır (ancak hata ayıklama sırasında yine de düşünülebilir). Tuşunu kullanarak raise ... from Noneyazdırmak istediğiniz bağlamı gizleyebilirsiniz.

raiseİfade belgelerine bakın :

fromMaddesi durum zincirleme için kullanılır: verilirse, ikinci sentezleme sonra da yükseltilmiş haricinde bağlı olacaktır Başka bir özel sınıfı veya örneği, olmalıdır __cause__(yazılabilir olan) öznitelik. Yükseltilen kural dışı durum ele alınmazsa, her iki kural dışı durum da yazdırılır:

>>> try:
...     print(1 / 0)
... except Exception as exc:
...     raise RuntimeError("Something bad happened") from exc
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened

Bir istisna işleyici veya finallyyan tümce içinde bir istisna ortaya çıkarsa benzer bir mekanizma örtük olarak çalışır : önceki istisna yeni istisnanın __context__niteliği olarak eklenir :

>>> try:
...     print(1 / 0)
... except:
...     raise RuntimeError("Something bad happened")
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened

Ayrıca , bağlamla ilgili ayrıntılar ve istisnalara eklenmiş neden bilgileri için Yerleşik İstisnalar belgelerine bakın.


11
Örtükleri kullanan fromve __cause__yerine istisnaları açıkça zincirlemek için herhangi bir neden var mı __context__? Kişinin yakaladığı durumdan farklı bir istisna ekleyeceği durumlar var exceptmı?
darkfeline

13
@ darkfeline: Veritabanı API'nizin web ve disk dahil olmak üzere çeşitli kaynaklardan açılış veritabanlarını desteklediğini varsayalım. Veritabanının açılması başarısız olursa API'niz her zaman bir yükseltecektir DatabaseError. Ancak başarısızlık, IOErrorbir dosyanın açılamaması veya bir HTTPErrorURL'nin çalışamaması nedeniyle ortaya çıkıyorsa, bu açıkça dahil etmek istediğiniz bağlamdır, bu nedenle API'yi kullanan geliştirici bunun nedenini ayıklayabilir. O anda kullanıyorsunuz raise DatabaseError from original_exception.
Martijn Pieters

4
@darkfeline: O geliştirici kendi API veritabanı API kullanımına sarma ve bu konuda geçmek isteniyorsa IOErrorveya HTTPErrorüzerine kendi tüketiciler, daha sonra kullanılmak olurdu raise NewException from databaseexception.__cause__şimdi farklı bir istisna kullanarak, DatabaseExceptiononlar sadece yakaladı.
Martijn Pieters

2
@ dan3: hayır, yok. İstisna zincirleme tamamen bir Python 3 özelliğidir.
Martijn Pieters

5
@ laike9m: İstisnayı işlerken foove yeni bir istisna oluşturmak istediğinizde mi kastediyorsunuz bar? Daha sonra doğrudan nedenraise bar from foo olan Python durumunu kullanabilir ve edinebilirsiniz . Eğer varsa yok kullanın , sonra da Python hâlâ her iki yazdırır, ancak devlet bu elden geçirilmeden sırasında , büyüdü , farklı mesaj, bayrağa hata işleme olası bir hata niyetindeydi. foo barfrom foofoobar
Martijn Pieters
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.