Python Error handling detailed _python

Source: Internet
Author: User
Tags error handling integer division in python

In the process of running the program, if an error occurred, you can agree to return an error code in advance, so that you can know if there is a mistake, and the cause of the error. It is very common to return an error code in an operating system-supplied call. For example, open the File function open (), the success of the return file descriptor (is an integer), error return-1.

It is inconvenient to use an error code to indicate whether an error is necessary, because the normal result that the function should return is mixed with the error code, causing the caller to use a large amount of code to determine whether the error occurs:

Copy Code code as follows:

def foo ():
R = some_function ()
If r== (-1):
Return (-1)
# do something
Return r

def bar ():
r = foo ()
If r== (-1):
print ' Error '
Else
Pass


Once an error occurs, it is escalated at the first level until a function can handle the error (for example, by outputting an error message to the user).

So high-level languages usually have a set of try...except...finally ... Error-handling mechanism, Python is no exception.

Try

Let's use an example to see the mechanism of try:

Copy Code code as follows:

Try
print ' Try ... '
r = 10/0
print ' Result: ', R
Except Zerodivisionerror, E:
print ' except: ', E
Finally
print ' finally ... '
print ' End '

When we think that some code may be wrong, we can run this code with a try, and if an error occurs, the subsequent code does not continue, but instead jumps directly to the error-handling code, which is the except statement block, after except, if there is a finally statement block, Executes the finally statement block, which completes.

The above code produces a division error when calculating 10/0:

Copy Code code as follows:

Try ...
Except:integer division or modulo by zero
Finally ...
End

As you can see from the output, when the error occurs, subsequent statement print ' Result: ', R will not be executed, except is executed because it captures the zerodivisionerror. Finally, a finally statement is executed. Then, the program continues to follow the process down.

If you change the divisor 0 to 2, the results are as follows:

Copy Code code as follows:

Try ...
Result:5
Finally ...
End

Because there is no error, the except statement block is not executed, but finally, if it does, it will be executed (there can be no finally statement).

You can also guess that there are many kinds of errors, and if different types of errors occur, it should be handled by a different except statement block. Yes, you can have multiple except to catch different types of errors:

Copy Code code as follows:

Try
print ' Try ... '
r = 10/int (' a ')
print ' Result: ', R
Except ValueError, E:
print ' ValueError: ', E
Except Zerodivisionerror, E:
print ' Zerodivisionerror: ', E
Finally
print ' finally ... '
print ' End '

the int () function may throw a valueerror, so we capture the valueerror with a except and capture zerodivisionerror with another except.

Also, if there are no errors, you can add an else after the except statement block, and the else statement is automatically executed when no errors occur:

Copy Code code as follows:

Try
print ' Try ... '
r = 10/int (' a ')
print ' Result: ', R
Except ValueError, E:
print ' ValueError: ', E
Except Zerodivisionerror, E:
print ' Zerodivisionerror: ', E
Else
print ' No error! '
Finally
print ' finally ... '
print ' End '

Python's error is also class, all the wrong types are inherited from Baseexception, so in the use of except should be noted that it not only captures the type of error, but also its subclasses also "catch". Like what:
Copy Code code as follows:

Try
Foo ()
Except StandardError, E:
print ' StandardError '
Except ValueError, E:
print ' ValueError '

The second except will never capture ValueError, because ValueError is a subclass of StandardError, and if so, it is captured by the first except.

All of the bugs in Python are derived from the Baseexception class, common error types and inheritance relationships look here:
Https://docs.python.org/2/library/exceptions.html

There is also a huge benefit of using try...except to catch errors, that is, you can cross multiple layers of calls, such as function main () invoke foo (), foo () call Bar (), and the bar () has an error, as long as main () is captured, you can handle:

Copy Code code as follows:

def foo (s):
return 10/int (s)

def bar (s):
return foo (s) * 2

def main ():
Try
Bar (' 0 ')
Except StandardError, E:
print ' error! '
Finally
print ' finally ... '


That is, there is no need to catch errors in every possible place, as long as you catch them at the right level. In this way, it greatly reduces the trouble of writing try...except...finally.

Call stack

If the error is not captured, it is thrown up, is finally captured by the Python interpreter, prints an error message, and the program exits. Look at err.py:

Copy Code code as follows:

# err.py:
def foo (s):
return 10/int (s)

def bar (s):
return foo (s) * 2

def main ():
Bar (' 0 ')

Main ()


Implementation, the results are as follows:
Copy Code code as follows:

$ python err.py
Traceback (most recent call last):
File "err.py", line one, in <module>
Main ()
File "err.py", line 9, in main
Bar (' 0 ')
File "err.py", line 6, in bar
return foo (s) * 2
File "err.py", line 3, in Foo
return 10/int (s)
Zerodivisionerror:integer division or modulo by zero

Error is not terrible, terrible is not know what went wrong. Interpreting error messages is the key to locating errors. We can see the entire wrong call function chain from the top down:

Error message Line 1th:

Copy Code code as follows:

Traceback (most recent call last):

Tell us this is the wrong tracking information.

Line 2nd:

Copy Code code as follows:

File "err.py", line one, in <module>
Main ()

There was an error calling main (), the 11th line of code file err.py, but the reason is line 9th:
Copy Code code as follows:

File "err.py", line 9, in main
Bar (' 0 ')

The call bar (' 0 ') was faulted, the code file err.py the 9th line of code, but the reason is line 6th:
Copy Code code as follows:

File "err.py", line 6, in bar
return foo (s) * 2

The reason for this is return foo (s) * 2, but this is not the final reason, keep looking down:
Copy Code code as follows:

File "err.py", line 3, in Foo
return 10/int (s)

The reason is that the return 10/int (s) statement has been faulted, which is the source of the error, because the following print:
Copy Code code as follows:

Zerodivisionerror:integer division or modulo by zero

Based on the error type Zerodivisionerror, we judged that int (s) itself did not make an error, but Int (s) returned 0, and error occurred while calculating 10/0, where the source of the error was found.

Logging Errors

If you do not catch errors, you can naturally have the Python interpreter print out the error stack, but the program is ended. Now that we can catch the error, we can print out the error stack and then analyze the cause of the error, and let the program continue.

Python's built-in logging module makes it easy to log error messages:

Copy Code code as follows:

# err.py
Import logging

def foo (s):
return 10/int (s)

def bar (s):
return foo (s) * 2

def main ():
Try
Bar (' 0 ')
Except StandardError, E:
Logging.exception (e)

Main ()
print ' End '


It is also an error, but the program continues to execute after printing the error message and exits normally:
Copy Code code as follows:

$ python err.py
ERROR:root:integer division or modulo by zero
Traceback (most recent call last):
File "err.py", line, in main
Bar (' 0 ')
File "err.py", line 8, in bar
return foo (s) * 2
File "err.py", line 5, in Foo
return 10/int (s)
Zerodivisionerror:integer division or modulo by zero
End

Through the configuration, logging can also log errors to the file, to facilitate the subsequent investigation.

Throw an error

Because the error is class, capturing an error is capturing an instance of that class. As a result, errors are not created out of thin air, but are intentionally made and thrown. Python's built-in functions throw out many types of errors, and the functions we write ourselves can also throw errors.

If you want to throw an error, you can first define an incorrect class, select a good inheritance relationship, and then throw an instance of the error with the Raise statement, depending on your needs:

Copy Code code as follows:

# err.py
Class Fooerror (StandardError):
Pass

def foo (s):
n = Int (s)
If n==0:
Raise Fooerror (' Invalid value:%s '% s)
Return 10/n


execution, you can finally trace to our own definition of the error:
Copy Code code as follows:

$ python err.py
Traceback (most recent call last):
...
__main__. Fooerror:invalid value:0

Define our own type of error only when necessary. If you can choose a built-in error type (such as valueerror,typeerror) that Python already has, try to use Python's built-in error type.

Finally, let's look at another way to handle the error:

Copy Code code as follows:

# err.py
def foo (s):
n = Int (s)
Return 10/n

def bar (s):
Try
return foo (s) * 2
Except StandardError, E:
print ' error! '
Raise

def main ():
Bar (' 0 ')

Main ()


In the bar () function, we obviously have caught the error, but, after printing a error!, and then the error through the raise statement thrown out, this is not sick?

In fact, this type of error handling is not only not sick, but also quite common. The purpose of capturing errors is simply to record and facilitate follow-up. However, since the current function does not know what to do with the error, the most appropriate way is to continue to throw it up and let the top level caller handle it.

The raise statement throws the current error as if it were not with an argument. In addition, raise an error in the except can also convert one type of fault to another:

Copy Code code as follows:

Try
10/0
Except Zerodivisionerror:
Raise ValueError (' Input error! ')

As long as it is reasonable to convert logic, however, a ioerror should never be converted into irrelevant valueerror.

Summary

Python's built-in try...except...finally is handy for handling errors. When an error occurs, parsing the error message and locating the code location where the error occurred is critical.

The program can also actively throw an error, allowing the caller to handle the corresponding error. However, you should write clearly in your document what errors might be thrown and why the error occurred.

Related Article

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.