1. What is the exception
During the running of the software program, it is very likely to encounter the problems just mentioned. We call them exceptions. The English is: Exception
, which means exceptions. When encountering these exceptions, or called exceptions, how can we make the written program handle it reasonably and exit safely without the program crashing?
At work, the situation encountered by the program cannot be perfect. For example: the program wants to open a certain file, the file may not exist or the file format is wrong; the program is running, but the memory or hard disk may be full, etc.
1. Pseudo-code description exception mechanism
If we want to copy a file, in the absence of an exception mechanism, we need to consider various exceptions. The pseudocode is as follows:
In this way, there are two disadvantages:
- Put logic code and error handling code together!
- The exceptions that programmers themselves need to consider are more complicated, and the requirements for programmers themselves are higher!
In the above situation, if Python’s exception mechanism is used to handle the situation, the comparison is as follows:
The essence of the exception mechanism : when an exception occurs in the program, the program exits safely and continues to execute after processing
In python, many classes used to describe and handle exceptions are introduced, called exception classes. The exception class definition contains the information of this type of exception and the method of handling the exception. The following is a more complete display of the inheritance hierarchy of built-in exception classes in python :
Everything in python is an object, and exceptions are also handled in the form of objects . Process:
- Throwing an exception: When executing a method, if an exception occurs, the method generates an object representing the exception, stops the current execution path, and submits the exception object to the interpreter.
- Catch exception: After the interpreter gets the exception, it looks for the corresponding code to handle the exception
Two, try and except structure
try...except
is the most common exception handling construct. The structure is as follows:
try:
被监控的可能引发异常的语句块
except BaseException [as e]:
异常处理语句块
try
Blocks contain code that may throw exceptions, andexcept
blocks are used to catch and handle exceptions that occur.- During execution, if
try
no exception is thrown in the block,ecept
the block is skipped and the subsequent code is executed; - During execution, if
try
an exception occurs in the block, skiptry
the subsequent code in the block and jump to the correspondingexcept
block to handle the exception; after the exception is handled, continue to execute the subsequent code.
Execution Sequence Encountered Exception
#测试简单的0不能做除数异常
try:
print("step1")
a = 3/0
print("step2")
except BaseException as e:
print("step3")
print(e)
print("step4")
除数为0,遇到异常输出结果:
step1
step3
division by zero
step4
Enter a number in a loop, and if it is not a number, handle an exception; until it is entered 88
, the loop ends.
while True:
try:
x = int(input("请输入一个数字:"))
print("您入的数字是",x)
if x==88:
print("退出程序")
break
except:
print("异常:输入的不是一个数字")
执行结果:
请输入一个数字:10
您入的数字是 10
请输入一个数字:abc
异常:输入的不是一个数字
请输入一个数字:88
您入的数字是 88
退出程序
Three, try...multiple except structures
The above structure can catch all exceptions, and it is very common in work. However, from the perspective of classical theory, it is generally recommended to try to catch as many exceptions as possible (in the order of first subclass and then parent class), and write exception handling code in a targeted manner. In order to avoid missing possible exceptions, it can be added at the end BaseException
. The structure is as follows:
try:
被监控的、可能引发异常的语句块
except Exception1:
处理Exception1的语句块
except Exception2:
处理Exception2的语句块
[...]
except BaseException:
处理可能遗漏的异常的语句块
multiple except
structures
try:
a = input("请输入被除数:")
b = input("请输入除数:")
c = float(a)/float(b)
print(c)
except ZeroDivisionError:
print("异常:除数不能为0")
except TypeError:
print("异常:除数和被除数都应该为数值类型")
except BaseException as e:
print(e)
print(type(e))
执行结果:
请输入被除数:10
请输入除数:0
异常:除数不能为0
Four, try...except...else structure
try...except...else
structure was added else块
. If try
no exception is thrown in the block, else
the block is executed. If try
an exception is thrown in the block, the block is executed except
, the block is not executed else
.
try...except...else
Structural Execution Test
try:
a = input("请输入被除数:")
b = input("请输入除数:")
c = float(a)/float(b)
except BaseException as e:
print(e)
else:
print("除的结果是:",c)
发生异常的执行情况(执行except块,没有执行else):
请输入被除数:5
请输入除数:0
float division by zero
没有发生异常的执行情况(执行完try块后,执行else):
请输入被除数:10
请输入除数:5
除的结果是: 2.0
Five, try...except...finally structure
try...except...finally
In the structure, finally
the block will be executed regardless of whether an exception occurs; it is usually used to release try
the resources allocated in the block.
try...except...finally
Structured Simple Test
try:
a = input("请输入一个被除数:")
b = input("请输入一个除数:")
c = float(a)/float(b)
except BaseException as e:
print(e)
else:
print(c)
finally:
print("我是finally中的语句,无论发生异常与否,都执行!")
print("程序结束!")
执行结果如下:
请输入被除数:10
请输入除数:0
float division by zero
我是finally中的语句,无论是否发生异常都执行
When reading a file, finally
ensure that the file resource is closed
try:
f = open("d:/a.txt",'r')
content = f.readline()
print(content)
except BaseException as e:
print(e)
finally:
f.close() #释放资源。此处也可能会发生异常。若发生异常,则程序终止,不会继续往下执行
print("step4")
发生异常的执行结果:
Traceback (most recent call last):
[Errno 2] No such file or directory: 'd:/a.txt'
File "...mypro_exception/my01.py", line 8, in <module>
f.close() #释放资源。此处也可能会发生异常。若发生异常,则程序终止,不会继续往下执行
NameError: name 'f' is not defined
Process finished with exit code 1
Six, return statement and exception handling issues
Because return
it has two functions: end method operation and return value. We generally don't return
put it in the exception handling structure, but put it at the end of the method.
return
and the correct way to handle the exception structure
def test01():
print("step1")
try:
x = 3/0
# return "a"
except:
print("step2")
print("异常:0不能做除数")
#return "b"
finally:
print("step4")
#return "d"
print("step5")
return "e"
#一般不要将return语句放到try、except、else、finally块中,会发生一些意想不到的错误。建议放到方法最后。
print(test01())
执行结果:
step1
step2
异常:0不能做除数
step4
step5
e
7. Common exceptions
SyntaxError
:Grammatical errors
int a =3
^
SyntaxError: invalid syntax
NameError
: Attempt to access an undeclared variable
print(a)
NameError: name 'a' is not defined
-
ZeroDivisionError
: Division by 0 error (division by zero error)
a = 3/0
ZeroDivisionError: division by zero
-
ValueError
: Value error
float("abc")
ValueError: could not convert string to float: 'abc'
TypeError
: type error
123+"abc"
TypeError: unsupported operand type(s) for +: 'int' and 'str'
-
AttributeError
: Access a non-existing property of an object
a=100
a.sayhi()
AttributeError: 'int' object has no attribute 'sayhi'
-
IndexError
: Index out of bounds exception
a = [4,5,6]
a[10]
IndexError: list index out of range
KeyError
: key of dictionary does not exist
a = {'name':"pig",'age':18}
a['salary']
KeyError: 'salary'
exception name | illustrate |
---|---|
ArithmeticError | Base class for all numerical calculation errors |
AssertionError | Assertion statement failed |
AttributeError | object does not have this property |
BaseException | Base class for all exceptions |
DeprecationWarning | Warning about deprecated features |
EnvironmentError | Base class for operating system errors |
EOFError | No builtin input, EOF marker reached |
Exception | Base class for general errors |
FloatingPointError | floating point calculation error |
FutureWarning | Warning about future semantic changes of constructs |
GeneratorExit | The generator (generator) has an exception to notify the exit |
ImportError | Failed to import module/object |
IndentationError | indentation error |
IndexError | There is no such index (index) in the sequence |
IOError | I/O operation failed |
KeyboardInterrupt | The user interrupts execution (usually by typing ^C) |
KeyError | The key does not exist in the map |
LookupError | Base class for invalid data queries |
MemoryError | Out of memory errors (not fatal to the Python interpreter) |
NameError | Object not declared/initialized (has no properties) |
NotImplementedError | methods not yet implemented |
OSError | operating system error |
OverflowError | Numerical operation exceeds maximum limit |
OverflowWarning | Old warning about autopromotion to long |
PendingDeprecationWarning | Warning about features being deprecated |
ReferenceError | Weak references attempt to access objects that have been garbage collected |
RuntimeError | generic runtime error |
RuntimeWarning | Warnings about suspicious runtime behavior |
StandardError | Base class for all built-in standard exceptions |
StopIteration | iterator has no more values |
SyntaxError | Python syntax error |
SyntaxWarning | Warning about suspicious syntax |
SystemError | General interpreter system errors |
SystemExit | 解释器请求退出 |
TabError | Tab 和空格混用 |
TypeError | 对类型无效的操作 |
UnboundLocalError | 访问未初始化的本地变量 |
UnicodeDecodeError | Unicode 解码时的错误 |
UnicodeEncodeError | Unicode 编码时错误 |
UnicodeError | Unicode 相关的错误 |
UnicodeTranslateError | Unicode 转换时错误 |
UserWarning | 用户代码生成的警告 |
ValueError | 传入无效的参数 |
Warning | 警告的基类 |
WindowsError | 系统调用失败 |
ZeroDivisionError | 除(或取模)零 (所有数据类型) |
八、with上下文管理
finally
块由于是否发生异常都会执行,通常我们放释放资源的代码。其实,我们可以通过with
上下文管理,更方便的实现释放资源的操作。
with
上下文管理的语法结构如下:
with context_expr [ as var]:
语句块
with
上下文管理可以自动管理资源,在with
代码块执行完毕后自动还原进入该代码之前的现场或上下文。不论何种原因跳出with
块,不论是否有异常,总能保证资源正常释放。极大的简化了工作,在文件操作、网络通信相关的场合非常常用。
with
上下文管理文件操作
with open("d:/bb.txt") as f:
for line in f:
print(line)
执行结果:
abc
def
ghi
九、traceback模块和生成异常日志
使用traceback
模块打印异常信息
import traceback
try:
print("step1")
num = 1/0
except:
traceback.print_exc()
运行结果:
step1
Traceback (most recent call last):
File "...mypro_exception/my01.py", line 7, in <module>
num = 1/0
ZeroDivisionError: division by zero
Process finished with exit code 0
使用traceback
将异常信息写入日志文件
#coding=utf-8
import traceback
try:
print("step1")
num = 1/0
except:
with open("d:/a.log","a") as f:
traceback.print_exc(file=f)
十、自定义异常类
程序开发中,有时候我们也需要自己定义异常类。自定义异常类一般都是运行时异常,通常继承Exception
或其子类即可。命名一般以Error
、Exception
为后缀。
自定义异常由raise
语句主动抛出。
自定义异常类和raise语句
#测试自定义异常类
class AgeError(Exception): #继承Exception
def __init__(self,errorInfo):
Exception.__init__(self)
self.errorInfo = errorInfo
def __str__(self):
return str(self.errorInfo)+",年龄错误!应该在1-150之间"
############测试代码################
if __name__ == "__main__": #如果为True,则模块是作为独立文件运行,可以执行测试代码
age = int(input("输入一个年龄:"))
if age<1 or age>150:
raise AgeError(age)
else:
print("正常的年龄:",age)
执行结果:
输入一个年龄:200
Traceback (most recent call last):
File "...mypro_exception/my10.py", line 16, in <module>
raise AgeError(age)
__main__.AgeError: 200,年龄错误!应该在1-150之间
自定义异常类一般都是运行时异常,通常继承Exception
或其子类即可。命名一般以Error
、Exception
为后缀。
自定义异常由raise
语句主动抛出。