Python Tutorial 学习(八)--Errors and Exceptions
Python Tutorial 学习(八)--Errors and Exceptions恢复
- Errors and Exceptions 错误与异常
此前,我们还没有开始着眼于错误信息.不过如果你是一路跟着例程走过来的,你就会发现一下错误信息.在Python里面至少有两类错误:语法错误和异常(syntax errors and exceptions)
8.1. Syntax Errors 语法错误
语法错误就是语法错误,语法错误就是语法错误.
比如说,关键词拼写错误,缩进错误,标点符号错误等等,比如下面这个栗子里面的在while循环的时候漏写了冒号引起的语法错误,注意错误提示中意既给出了具体的出错地点,
'^'直观的给出了位置.
while True print 'Hello world'
File "", line 1, in ?
while True print 'Hello world'
^
SyntaxError: invalid syntax
8.2. Exceptions 异常
即使是程序中没有了语法上的错误,但是有时候我们还是会出一些幺蛾子,这个就是异常了.这里我需要告诉你的就是,在Python里面,异常是可以被控制并处理的.
举一个栗子:
10 * (1/0)
Traceback (most recent call last):
File "", line 1, in ?
ZeroDivisionError: integer division or modulo by zero
4 + spam*3
Traceback (most recent call last):
File "", line 1, in ?
NameError: name 'spam' is not defined
'2' + 2
Traceback (most recent call last):
File "", line 1, in ?
TypeError: cannot concatenate 'str' and 'int' objects
上面栗子里面引起了异常,第一个是零作为除数的异常,第二个则是引用一个不存在的变量引起的异常,第三个是不同类似格式的数据相加的异常
8.3. Handling Exceptions 异常的处理
Python通常情况下的的异常处理是借助try...except...组合来实现的,将需要运行的相关程序代码放在try except之间,将引起异常时候的后续处理放在except后的代码中.比如这样
try:
do something
except:
print 'error appear while doing something'
这里再给出try except的运行流程:
The try statement works as follows.
First, the try clause (the statement(s) between the try and except keywords) is executed.
If no exception occurs, the except clause is skipped and execution of the try statement is finished.
If an exception occurs during execution of the try clause, the rest of the clause is skipped. Then if its type matches the exception named after the except keyword, the except clause is executed, and then execution continues after the try statement.
If an exception occurs which does not match the exception named in the except clause, it is passed on to outer try statements; if no handler is found, it is an unhandled exception and execution stops with a message as shown above.
意思就是说,在try表达式中代码的运行顺序是按照下面这样来的:
首先,直接执行try和except之间的代码,如果没有引起异常,那么except中的表达式就不会执行,如果异常产生了,那么产生异常的代码后面的表达式将会被终止运行,然后会将异常与except中的异常类型进行匹配,匹配到则执行except部分的代码.
如果except中给定的异常类型没有匹配到,那么try except将会终止并给出一个错误信息.
当然,如果你不想处理产生的某些异常,也可以直接丢弃,在程序编码上应该是这样的:
try:
do something
except Exception, e: #except后面继承的异常类是可选字段,也可以直接省略不写,因为except默认继承Exception(这是所有异常的基类)
pass # this will do nothing
举个栗子,有选择的处理一类或者几类异常,其余的异常简单丢弃:
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as e:
print "I/O error({0}): {1}".format(e.errno, e.strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise
try except表达式还有一个可选的else分支,用于在try except无异常执行完毕后继续执行相关的代码,注意else必须置于所有的except之后.这在某些情况下是很有用的,比如下面的一个栗子,在成功打开文件后将文件内容输出:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print 'cannot open', arg
else:
print arg, 'has', len(f.readlines()), 'lines'
f.close()
8.4. Raising Exceptions 异常的产生
raise 表达式运行程序强制抛出一个异常,栗子来了:
raise NameError('HiThere')
Traceback (most recent call last):
File "", line 1, in ?
NameError: HiThere
暂时用到的不多,这里就简单的介绍一点点
8.5. User-defined Exceptions 自定义异常
嫌弃Python自带的异常不够详细?那么也可以选择自定义一些异常,比如这样:
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
raise MyError('oops!')
Traceback (most recent call last):
File "", line 1, in ?
main.MyError: 'oops!'
8.6. Defining Clean-up Actions 定义'收尾'的动作
try表达式有一个可选的表达式finally,它总是执行,不管有没有出现异常,比如这样:
try:
... raise KeyboardInterrupt
... finally:
... print 'Goodbye, world!'
...
Goodbye, world!
KeyboardInterrupt
再结合上面学的一点,我们甚至可以这样来一发:
try:
do something
except:
do another thing
else:
do something after successed while trying
finally:
always do something no matter success or failure
8.7. Predefined Clean-up Actions 这是嘛意思??? orz...
当然,真正到需要知道的时候,我可能不得不来弄明白这一堆到底写的是啥...
原文放下面:
Some objects define standard clean-up actions to be undertaken when the object is no longer needed, regardless of whether or not the operation using the object succeeded or failed. Look at the following example, which tries to open a file and print its contents to the screen.
for line in open("myfile.txt"):
print line,
The problem with this code is that it leaves the file open for an indeterminate amount of time after the code has finished executing. This is not an issue in simple scripts, but can be a problem for larger applications. The with statement allows objects like files to be used in a way that ensures they are always cleaned up promptly and correctly.
with open("myfile.txt") as f:
for line in f:
print line,
After the statement is executed, the file f is always closed, even if a problem was encountered while processing the lines. Other objects which provide predefined clean-up actions will indicate this in their documentation.
耐着性子看完了,大概是看懂了,
预定义'收尾'的工作,然后解释了一番,有些时一些毛病不治好可能无伤大雅,但真正放到更复杂的环境中可能就是一个坑,比如说,在单文件脚本中,打开一个文件不关闭的话,可能不会有什么问题产生,但是如果是在项目中这样做的话,可能就会产生问题. with 让这些变得简单粗暴又安全.
栗子里面,with open(xxx) as f:.....执行完毕够狠,文件f总是被关闭了,即使是在代码执行过程中产生了异常,还是被关闭了,尊好.