Išskirtinis atsekimas yra paslėptas, o ne tuoj pat sukilęs

Turiu panašų kodą:

 import sys def func1(): func2() def func2(): raise Exception('test error') def main(): err = None try: func1() except: err = sys.exc_info()[1] pass # some extra processing, involving checking err details (if err is not None) # need to re-raise err so caller can do its own handling if err: raise err if __name__ == '__main__': main() 

Kai func2 kelia išimtį, gaunu tokį pėdsaką:

 Traceback (most recent call last): File "err_test.py", line 25, in <module> main() File "err_test.py", line 22, in main raise err Exception: test error 

Iš čia nematau, iš kur išimtis. Pradinis pėdsakas prarandamas.

Kaip išlaikyti originalų pėdsaką ir jį pakelti? Noriu pamatyti kažką panašaus:

 Traceback (most recent call last): File "err_test.py", line 26, in <module> main() File "err_test.py", line 13, in main func1() File "err_test.py", line 4, in func1 func2() File "err_test.py", line 7, in func2 raise Exception('test error') Exception: test error 
53
28 янв. nustatė parxier Jan 28 2011-01-28 08:42 '11 at 8:42 2011-01-28 08:42
@ 5 atsakymai

Tuščias raise sukelia paskutinę išimtį.

 # need to re-raise err so caller can do its own handling if err: raise 

Jei naudosite raise something , „Python“ negali žinoti, ar ši išimtis something tiesiog sugauta anksčiau, ar nauja išimtis su nauju kamino pėdsaku. Štai kodėl yra tuščias raise kuris išsaugo kamino pėdsaką.

Nuoroda čia

89
28 янв. Jochen Ritzel atsakymas 2011-01-28 08:51 '11 at 8:51 2011-01-28 08:51

Galite keisti ir atkurti išimtį:

Jei nėra jokios išraiškos, raise dar kartą iškelkite paskutinę išimtį, kuri buvo aktyvi dabartinėje taikymo srityje. Jei pagal dabartinę taikymo sritį, „ TypeError išimtis, rodanti, kad tai yra klaida (jei ji vykdoma pagal IDLE, vietoj to Queue.Empty ).

Priešingu atveju, raise vertinimus išraiškų, kad gautumėte tris objektus, naudodami None kaip trūkstamų išraiškų vertę. Pirmieji du objektai naudojami išimties tipui ir vertei nustatyti.

Jei yra trečiasis objektas, o ne None , jis turėtų būti pėdsako objektas (žr. Skyrių „Tipo tipo hierarchija“), o ne vietoj dabartinės vietos, o ne išimties. Jei yra trečiasis objektas, o ne pėdsako objektas arba None , išimtis yra TypeError išimtis.

Trijų dimensijų išraiškos formos raise yra naudingas siekiant skaidriai atkurti išimtį, except , bet raise be išraiškų turėtų būti teikiama pirmenybė, jei išimtis, kuri turi būti iškelta, buvo paskutinė aktyvi išimtis dabartinėje taikymo srityje.

Taigi, jei norite pakeisti išimtį ir ją pakeisti, galite tai padaryti:

 try: buggy_code_which_throws_exception() except Exception as e: raise Exception, "The code is buggy: %s" % e, sys.exc_info()[2] 
52
04 янв. atsakymas pateikiamas qris 04 Jan 2013-01-04 21:03 '13, 21:03 2013-01-04 21:03

Su sys.exc_info() galite gauti daugybę išimčių informacijos su traceback moduliu

Išbandykite toliau pateiktą savo kodo plėtinį.

 import sys import traceback def func1(): func2() def func2(): raise Exception('test error') def main(): try: func1() except: exc_type, exc_value, exc_traceback = sys.exc_info() # Do your verification using exc_value and exc_traceback print "*** print_exception:" traceback.print_exception(exc_type, exc_value, exc_traceback, limit=3, file=sys.stdout) if __name__ == '__main__': main() 

Jis bus spausdinamas, kaip ir norėjote.

 *** print_exception: Traceback (most recent call last): File "err_test.py", line 14, in main func1() File "err_test.py", line 5, in func1 func2() File "err_test.py", line 8, in func2 raise Exception('test error') Exception: test error 
3
28 янв. Atsakymas, kurį pateikė Senthil Kumaran Jan 28 2011-01-28 08:48 '11, 8:48, 2011-01-28 08:48

Jūsų pagrindinė funkcija turėtų atrodyti taip:

 def main(): try: func1() except Exception, err: # error processing raise 

Tai yra standartinis būdas tvarkyti (ir pakartotinai pakelti) klaidas. Čia pateikiamas kodo demonstravimas .

1
28 янв. atsakymas, kurį pateikė Gabi Purcaru Jan 28 2011-01-28 08:50 '11 at 8:50 2011-01-28 08:50

Nors „@Jochen“ atsakymas paprastu atveju veikia gerai, jis negali tvarkyti sudėtingesnių atvejų, kai nesistengiate perimti ir rekonstruoti, bet dėl ​​kokios nors priežasties išimtis pateikiama kaip objektas ir norite vėl mesti į visiškai naują kontekstą (t.y. jei reikia jį apdoroti kitame procese).

Tokiu atveju siūlau:

  • gauti originalų „exc_info“
  • formatuokite pradinį klaidos pranešimą su pėdsaku
  • įveskite naują išimtį su visu klaidos pranešimu (įskaitant kamino pėdsaką).

Prieš tai atlikdami nustatykite naują išimties tipą, kuris vėliau bus pašalintas ...

 class ChildTaskException(Exception): pass 

Pažeidimo kode ...

 import sys import traceback try: # do something dangerous except: error_type, error, tb = sys.exc_info() error_lines = traceback.format_exception(error_type, error, tb) error_msg = ''.join(error_lines) # for example, if you are doing multiprocessing, you might want to send this to another process via a pipe connection.send(error_msg) 

Rethrow ...

 # again, a multiprocessing example of receiving that message through a pipe error_msg = pcon.recv() raise ChildTaskException(error_msg) 
1
11 апр. atsakymas pateikiamas tvt173 11 balandžio. 2017-04-11 03:42 '17 at 3:42 2017-04-11 03:42