An in-depth analysis of Python's re-throwing exceptions

Source: Internet
Author: User

Exceptions are important for a language, and exception stack information is particularly important for developers because the exception stack can be used to find the first place to throw an exception. But there are not many people who know the right thing to throw an exception.

First of all, here are the worst

Def revert_stuff ():
Pass

Def some_code ():
Raise Exception (' Oops, some error occur ')

Try
Some_code ()
Except
Revert_stuff ()
Raise Exception ("Some_code failed!")
Traceback (most recent call last):
File "1.py", line one, in <module>
Raise Exception ("Some_code failed!")
Exception:some_code failed!
Why is that the worst? Because all of the failure information about Some_code () is lost. However, these exception stacks may be the information we expect, or they may not be.

The following code has been slightly improved, but is still not very good:

Def revert_stuff ():
Pass

Def some_code ():
Raise Exception (' Oops, some error occur ')

Try
Some_code ()
Except
Import Traceback
Traceback.print_exc ()
Revert_stuff ()
Raise Exception ("Some_code failed!")
Traceback (most recent call last):
File "2.py", line 8, in <module>
Some_code ()
File "2.py", line 5, in Some_code
Raise Exception (' Oops, some error occur ')
Exception:oops, some error occur
Traceback (most recent call last):
File "2.py", line, in <module>
Raise Exception ("Some_code failed!")
Exception:some_code failed!
Use Traceback.print_exc () to print out the original exception stack (traceback). From some point of view this is the best way, because you can find the exception of the error message. But if you do not want to recover the new exception information, you should do so:

Def revert_stuff ():
Pass

Def some_code ():
Raise Exception (' Oops, some error occur ')

Try
Some_code ()
Except
Revert_stuff ()
Raise
Traceback (most recent call last):
File "3.py", line 8, in <module>
Some_code ()
File "3.py", line 5, in Some_code
Raise Exception (' Oops, some error occur ')
Exception:oops, some error occur
You can raise the last exception with no arguments. Sometimes people leave blank without except: statements, but this particular form (except: + Raise) is OK.

There is another kind of raise throws the unusual way, knows the person is relatively few, but also very easy to start. Like raise without parameters, this method can also preserve the exception stack:

Def some_code ():
Raise Exception (' Oops, some error occur ')

def maybe_raise (Exc_info):
Raise Exc_info[0], exc_info[1], exc_info[2]

Try
Some_code ()
Except
Import Sys
Exc_info = Sys.exc_info ()
Maybe_raise (Exc_info)
Traceback (most recent call last):
File "4.py", line, in <module>
Maybe_raise (Exc_info)
File "4.py", line 8, in <module>
Some_code ()
File "4.py", line 2, in Some_code
Raise Exception (' Oops, some error occur ')
Exception:oops, some error occur
If you need to handle exceptions elsewhere in the code where the exception occurs, it's a good choice. But usually it is not very convenient, because it is more obscure and difficult to understand.

Another category that frequently modifies the exception stack is the need to add additional information to the exception stack.

For Lineno, line in enumerate (file):
Try
Process_line (line)
Except Exception, exc:
Raise Exception ("Error in line%s:%s"% (Lineno, exc))
The exception information is preserved, but the exception stack is lost. There is a way to preserve the exception stack. The following methods can not only preserve exceptions, but also change the information of exceptions.

Except Exception, exc:
args = Exc.args
If not args:
arg0 = ' '
Else
arg0 = Args[0]
arg0 + = ' at line%s '% Lineno
Exc.args = arg0 + args[1:]
Raise
Some little embarrassment. Technically (although it is not recommended), you can throw any exception. If you use except Exception: Then you cannot capture some such as string exceptions or other exceptions. Wanting to do this depends on whether you care about the scenes. However, exceptions may not have the. Args property, or the string information for the exception cannot be obtained from these parameters, or there are other methods of presentation (for example, keyerror information is somewhat different). So this is not a panacea. Want to enhance the version, you can do this:

Except
Exc_class, exc, TB = Sys.exc_info ()
Exc_class is a string type, but someone might raise "not found". So this style has been abandoned. If you insist on trying to make a mess of what's around you, you can use it:

New_exc = Exception ("Error in line%s:%s")
% (Lineno, exc or Exc_class))
Raise New_exc.__class__, New_exc, TB
This changes the clutter around the exception class, but preserves at least the good exception stack. Raise ValueError (...) in the exception stack. Or raise exception may look strange in the error message.

Summary: A better method in Python2

Here's a better way to throw out an exception in Python2.

Try
Code ()
Except
Exc_info = Sys.exc_info ()
Try
Revert_stuff ()
Except
# If This happens, it clobbers exc_info, which is why we had
# to save it above
Import Traceback
Print >> Sys.stderr, "Error in Revert_stuff ():"
Traceback.print_exc ()
Raise Exc_info[0], exc_info[1], exc_info[2]
Throw an exception in the WITH statement

If you want to keep an exception in some scenes and you want to not catch the exception in some scenarios, what can you do

Class Ignore_or_reraise_exception (object):
def __init__ (self, reraise=true):
Self.reraise = reraise

def __enter__ (self):
Self.type_, Self.value, SELF.TB, = Sys.exc_info ()
return self

def __exit__ (self, exc_type, Exc_val, EXC_TB):
If Exc_type is not None:
If self.reraise:
Log.error (' Original exception being dropped:%s '% self.value)
If self.reraise:
Return True # Reraise exception
Return False # Ignore exception

....
Except Exception:
With Ignore_or_reraise_exception (Reraise=false) as Ctxt:
If statements to determine whether to raise a new exception:
# not raising a new exception, so reraise
Ctxt.reraise = True
In this way, the freedom to choose is to ignore the exception, or to continue to throw the exception. When an exception needs to be thrown, the specified property Ctxt.reraise = True.

In addition, you can handle the exception in Ignore_or_reraise_exception, you can collect the exception to a global variable, the last program exit, all the exceptions are printed out.

Summary: Www.111cn.net compatible Python2, Python3, and the method of re-throwing exceptions

In Python2, the exception is thrown back with three parameters, raise Exc_info[0], exc_info[1], exc_info[2. But it's not the same in Python3.

This time only use compatible Python2, Python3 class library six.

How to use

Def some_code ():
Raise Exception (' Oops, some error occur ')

Class Swaggervalidationerror (Exception):
Pass

Try
Some_code ()
Except Exception as E:
Import Six, sys
Six.reraise (
Swaggervalidationerror,
Swaggervalidationerror (str (e)),
Sys.exc_info () [2])

Traceback (most recent call last):
File "5.py", line, in <module>
Sys.exc_info () [2])
File "5.py", line 8, in <module>
Some_code ()
File "5.py", line 2, in Some_code
Raise Exception (' Oops, some error occur ')
__main__. Swaggervalidationerror:oops, some error occur

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.