1. 语法错误
Python 的语法错误被称为解析错,语法分析器会指出出错的代码行,并且在最先找到的错误的位置标记一个小小的箭头。
>>> while True
File "<stdin>", line 1
while True
^
SyntaxError: invalid syntax
2. 异常
即使 Python 程序的语法是正确的,但是在运行的时候,也有可能发生错误,运行期监测到的错误称为异常。
>>> print(name)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'name' is not defined
>>> a = [1, 2, 3]
>>> b = a(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'list' object is not callable
>>> 10 / 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
3. 异常处理
try 语句按照以下方式工作:
- 首先,执行 try 子句,也就是在 try 和 except 之间的语句
- 如果没有异常发生,忽略 except 子句,程序继续运行
- 如果在 try 子句执行过程中发生了异常,那么 try 子句余下的部分将被忽略
- 若异常的类型和 except 之后的名称相符,那么对应的 except 子句将被执行,然后再执行 try 语句之后的代码
- 若异常没有与任何的 except 匹配,那么这个异常将会传递到上层的 try 中去
while True:
try:
x = int(input("Please enter a number: "))
break
except ValueError:
print("Oops! That was no valid number. Try again!")
Please enter a number: we
Oops! That was no valid number. Try again!
Please enter a number: sd
Oops! That was no valid number. Try again!
Please enter a number: 23
在上面的例子中,我们让用户通过键盘来输入一个合法的整数。如果输入的是字符串,那 int 函数就无法将字符串转为整数,程序就会抛出一个异常,然后执行 except 子句,打印信息提示我们重新输入,直到输入一个整数程序 break 结束。
一个 except 子句可以同时处理多个异常,这些异常被放在一个括号里成为一个元组。
except (RuntimeError, TypeError, NameError):
pass
最后一个 except 子句可以忽略异常的名称,它将被当做通配符使用。此时可以打印出错误信息,然后再次把异常抛出。
import sys
try:
f = open('test.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
# 没有相应文件时报错
OS error: [Errno 2] No such file or directory: 'test.txt'
# 文件中第一行为字符串无法转化为整数时报错
Could not convert data to an integer.
try except 语句还有一个可选的 else 子句,如果使用这个子句,那么必须放在所有的 except 子句之后。这个子句将在try子句没有发生任何异常的时候执行。
import sys
try:
f = open('test.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
else:
print(i)
# 1
使用 else 子句比把所有语句都放在 try 子句里面要好,这样可以避免一些意想不到的而 except 又没有捕获到的异常。
异常处理也可以处理子句中调用函数甚至是间接调用函数里抛出的异常。
3. 用户自定义异常
我们可以通过创建一个新的异常类来拥有自己的异常。异常类继承自 Exception,可以直接继承,或者间接继承。
class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
try:
raise MyError(2*2)
except MyError as e:
print('My exception occurred, value:', e.value)
# My exception occurred, value: 4
4. 定义清理行为
try 语句还有另外一个可选的子句 finally,它定义了无论任何情况下都会执行的清理行为。
def divide(x, y):
try:
result = x / y
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
finally:
print("executing finally clause")
divide(2, 1)
result is 2.0
executing finally clause
divide(2, 0)
division by zero!
executing finally clause
divide('2', '1')
executing finally clause
TypeError Traceback (most recent call last)
<ipython-input-19-0fe65f250ff1> in <module>()
----> 1 divide('2', '1')
<ipython-input-16-fb375c737bea> in divide(x, y)
1 def divide(x, y):
2 try:
----> 3 result = x / y
4 except ZeroDivisionError:
5 print("division by zero!")
TypeError: unsupported operand type(s) for /: 'str' and 'str'
一些对象定义了标准的清理行为,当程序中不需要它的时候,那么这个标准行为就会执行。关键词 with 语句可以保证诸如文件之类的对象在使用完之后一定会正确=地执行清理行为。
参考资料 菜鸟教程
获取更多精彩,请关注「seniusen」!