Exception Handling in Python

Source: Internet
Author: User
Tags integer division

Exception Handling in Python

This article mainly introduces how to parse the exception handling in Python. Exception Handling is an important knowledge to learn every programming language. The code in this article is based on Python2.x. For more information, see

In the process of running the program, if an error occurs, you can agree to return an error code in advance, so that you can know whether the error is correct and the cause of the error. In calls provided by the operating system, return error codes are very common. For example, if the open () function is used to open a file, the file descriptor (an integer) is returned when the file is successfully opened, and-1 is returned when an error occurs.

It is inconvenient to use the error code to indicate whether an error occurs. Because the normal results returned by the function itself are mixed with the error code, the caller must use a large amount of code to determine whether an error occurs:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

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 must be reported at the first level until a function can handle the error (for example, output an error message to the user ).

Therefore, advanced languages usually have built-in error handling mechanisms such as try... finally.... Python is no exception.

Try

Let's use an example to look at the try mechanism:

?

1

2

3

4

5

6

7

8

9

Try:

Print 'try ...'

R = 10/0.

Print 'result: ', r

Except t ZeroDivisionError, e:

Print 'success T: ', e

Finally:

Print 'Finally ...'

Print 'end'

When we think that some code may have errors, we can use try to run this code. If an error occurs during execution, the subsequent code will not continue to be executed, but will jump directly to the error handling code, that is, explain T statement block. After execution of explain T, if there is a finally statement block, execute the finally statement block. At this point, the execution is complete.

The above code will produce a division operation error when calculating 10/0:

?

1

2

3

4

Try...

Partition T: integer division or modulo by zero

Finally...

END

As can be seen from the output, when an error occurs, the subsequent statement print 'result: 'and r will not be executed, and the Progress T is executed because ZeroDivisionError is captured. Finally, the finally statement is executed. Then, the program continues to follow the process.

If the divisor 0 is changed to 2, the execution result is as follows:

?

1

2

3

4

Try...

Result: 5

Finally...

END

Because no error occurs, the explain T statement block will not be executed, but if finally exists, it will be executed (the finally statement may not exist ).

You can also guess that there should be many types of errors. If there are different types of errors, they should be processed by different blocks of the except T statement. Yes, there can be multiple escape t to capture different types of errors:

?

1

2

3

4

5

6

7

8

9

10

11

Try:

Print 'try ...'

R = 10/int ('A ')

Print 'result: ', r

Failed t ValueError, e:

Print 'valueerror: ', e

Except t ZeroDivisionError, e:

Print 'zerodivisionerror: ', e

Finally:

Print 'Finally ...'

Print 'end'

The int () function may throw a ValueError. Therefore, we use a counter t to capture the ValueError and another counter t to capture the ZeroDivisionError.

In addition, if no error occurs, you can add an else next to the limit t statement block. When no error occurs, the else statement is automatically executed:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

Try:

Print 'try ...'

R = 10/int ('A ')

Print 'result: ', r

Failed t ValueError, e:

Print 'valueerror: ', e

Except t ZeroDivisionError, e:

Print 'zerodivisionerror: ', e

Else:

Print 'no error! '

Finally:

Print 'Finally ...'

Print 'end'

Python errors are actually class. All error types are inherited from BaseException. Therefore, when using the handle T, you must note that it not only captures errors of this type, also, the sub-classes are "exhausted ". For example:

?

1

2

3

4

5

6

Try:

Foo ()

Counter t StandardError, e:

Print 'standardderror'

Failed t ValueError, e:

Print 'valueerror'

ValueError is never captured by the second counter T, because ValueError is a subclass of StandardError. If yes, it is also captured by the first counter T.

All Python errors are derived from the BaseException class. For common error types and inheritance relationships, see here:

Https://docs.python.org/2/library/exceptions.html#exception-hierarchy

Use try... another major advantage of using t to capture errors is that it can be called across multiple layers. For example, the function main () calls foo (), foo () calls bar (), and the result bar () has an error, at this time, as long as main () is captured, it can be processed:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

Def foo (s ):

Return 10/int (s)

 

Def bar (s ):

Return foo (s) * 2

 

Def main ():

Try:

Bar ('0 ')

Counter t StandardError, e:

Print 'error! '

Finally:

Print 'Finally ...'

That is to say, you do not need to capture errors in every possible error. You only need to capture errors at the appropriate level. In this way, the trouble of writing try... faster t... finally is greatly reduced.

Call Stack

If the error is not captured, it will be thrown up until it is captured by the Python interpreter, print an error message, and exit the program. Let's take a look at err. py:

?

1

2

3

4

5

6

7

8

9

10

11

# Err. py:

Def foo (s ):

Return 10/int (s)

 

Def bar (s ):

Return foo (s) * 2

 

Def main ():

Bar ('0 ')

 

Main ()

The result is as follows:

?

1

2

3

4

5

6

7

8

9

10

11

$ Python err. py

Traceback (most recent call last ):

File "err. py", line 11, 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

The error is not terrible. The terrible thing is that you don't know where the error is. Interpreting error messages is the key to identifying errors. We can see the entire incorrect call function chain from the top down:

Error message row 1st:

?

1

Traceback (most recent call last ):

This is the error tracking information.

Row 3:

?

1

2

File "err. py", line 11, in <module>

Main ()

An error occurred while calling main (). In the code file err. py, the code is in line 2, but the reason is 11th:

?

1

2

File "err. py", line 9, in main

Bar ('0 ')

An error occurred while calling bar ('0'). The error occurs in the code file err. py's 9th lines of code, but the reason is 6th lines:

?

1

2

File "err. py", line 6, in bar

Return foo (s) * 2

The reason is that the return foo (s) * 2 Statement has an error, but this is not the final reason. Continue to the following:

?

1

2

File "err. py", line 3, in foo

Return 10/int (s)

The reason is that the return 10/int (s) statement has an error. This is the source of the error because it is printed below:

ZeroDivisionError: integer division or modulo by zero

Based on the error type ZeroDivisionError, we can determine that int (s) itself has no error, but int (s) returns 0. An error occurs when 10/0 is calculated. At this point, locate the error source.

Record Error

If you do not capture the error, You can naturally let the Python interpreter print the error stack, but the program is also ended. Now that we can capture errors, we can print out the error stack and analyze the cause of the error. At the same time, let the program continue to run.

The Python built-in logging module can easily record error information:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

# Err. py

Import logging

 

Def foo (s ):

Return 10/int (s)

 

Def bar (s ):

Return foo (s) * 2

 

Def main ():

Try:

Bar ('0 ')

Counter t StandardError, e:

Logging. exception (e)

 

Main ()

Print 'end'

It is also an error, but the program continues to run after printing the error message and Exits normally:

?

1

2

3

4

5

6

7

8

9

10

11

$ Python err. py

ERROR: root: integer division or modulo by zero

Traceback (most recent call last ):

File "err. py", line 12, 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 configuration, logging can also record errors to log files for later troubleshooting.

Throw an error

Because the error is a class, capturing an error is to capture an instance of this class. Therefore, errors are not generated out of thin air, but intentionally created and thrown. The built-in functions of Python throw many types of errors, and the functions we compile can also throw errors.

If you want to throw an error, You can first define a wrong class as needed, select the inheritance relationship, and then use the raise statement to throw an error instance:

?

1

2

3

4

5

6

7

8

9

# Err. py

Class FooError (StandardError ):

Pass

 

Def foo (s ):

N = int (s)

If n = 0:

Raise FooError ('invalid value: % s' % s)

Return 10/n

Run the command to track the custom errors:

?

1

2

3

4

$ Python err. py

Traceback (most recent call last ):

...

_ Main _. FooError: invalid value: 0

We define our own error types only when necessary. If you can select an existing Python built-in error type (such as ValueError and TypeError), try to use the Python built-in error type.

Finally, let's look at another method of error handling:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

# Err. py

Def foo (s ):

N = int (s)

Return 10/n

 

Def bar (s ):

Try:

Return foo (s) * 2

Counter t StandardError, e:

Print 'error! '

Raise

 

Def main ():

Bar ('0 ')

 

Main ()

In the bar () function, an Error is clearly captured, but an Error is printed! And then throw the error through the raise statement. Isn't it true?

In fact, this error handling method is not only not ill, but also quite common. The purpose of capturing an error is to record it for later tracking. However, since the current function does not know how to handle the error, the most appropriate way is to continue to throw and let the top-level caller handle the error.

If the raise statement does not contain parameters, the current error is thrown as is. In addition, raise an Error in counter t can also convert one type of Error to another type:

?

1

2

3

4

Try:

10/0

Except t ZeroDivisionError:

Raise ValueError ('input error! ')

As long as the conversion logic is reasonable, an IOError should never be converted into an unrelated ValueError.

Summary

Python's built-in try... try t... finally is very convenient to handle errors. When an error occurs, it is critical to analyze the error information and locate the Code where the error occurs.

The program can also throw an error to allow the caller to handle the error. However, you should clearly write in the document what errors may be thrown and the causes of the errors.

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.