码迷,mamicode.com
首页 > 编程语言 > 详细

python异常处理

时间:2015-08-05 06:29:26      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:

 

一、异常的捕获
    异常的捕获有以下几种方法:
  

  1:使用try和except语句

    try:
        block
    except [exception,[data…]]:
        block
    try:
        block
    except [exception,[data...]]:
        block
    else:
        block


该种异常处理语法的规则是:
• 执行try下的语句,如果引发异常,则执行过程会跳到第一个except语句。
• 如果第一个except中定义的异常与引发的异常匹配,则执行该except中的语句。
• 如果引发的异常不匹配第一个except,则会搜索第二个except,允许编写的except数量没有限制。
• 如果所有的except都不匹配,则异常会传递到下一个调用本代码的最高层try代码中。
• 如果没有发生异常,则执行else块代码。
示例代码:

   
try:
        f = open(“file.txt”,”r”)
    except IOError, e:
        print e


    捕获到的IOError错误的详细原因会被放置在对象e中,然后运行该异常的except代码块,也可以使用以下方法来捕获所有的异常:

  

  try:
        a=b
        b=c
    except Exception,ex:
        print Exception,":",ex


 

    使用except子句需要注意的事情,就是多个except子句截获异常时,如果各个异常类之间具有继承关系,则子类应该写在前面,否则父类将会直接截获子类异常,放在后面的子类异常也就不会执行到了。

    2:使用try跟finally

 
   try:
        block
    finally:
        block


该语句的执行规则是:
• 执行try下的代码。
• 如果发生异常,在该异常传递到下一级try时,执行finally中的代码。
• 如果没有发生异常,则执行finally中的代码。

    第二种try语法在无论有没有发生异常都要执行代码的情况下是很有用的,例如我们在python中打开一个文件进行读写操作,我在操作过程中不管是否出现异常,最终都是要把该文件关闭的。
    这两种形式相互冲突,使用了一种就不允许使用另一种,而功能又各异。

    二、手工引发引发一个异常
    在Python中,要想引发异常,最简单的形式就是输入关键字raise,后跟要引发的异常的名称。异常名称标识出具体的类:Python异常是那些类的对象,执行raise语句时,Python会创建指定的异常类的一个对象,raise语句还可指定对异常对象进行初始化的参数,为此,请在异常类的名称后添加一个逗号以及指定的参数(或者由参数构成的一个元组)。
示例代码:

 
   try:
        raise MyError #自己抛出一个异常
    except MyError:
        print a error
    raise ValueError,invalid argument

捕捉到的内容为:

 

   type = VauleError
    message = invalid argument


 

    三、跟踪查看异常
    发生异常时,Python能“记住”引发的异常以及程序的当前状态,Python还维护着traceback(跟踪)对象,其中含有异常发生时与函数调用堆栈有关的信息,异常可能在一系列嵌套较深的函数调用中引发,程序调用每个函数时,Python会在“函数调用堆栈”的起始处插入函数名,一旦异常被引发,Python会搜索一个相应的异常处理程序。
    如果当前函数中没有异常处理程序,当前函数会终止执行,Python会搜索当前函数的调用函数,并以此类推,直到发现匹配的异常处理程序,或者Python抵达主程序为止,这一查找合适的异常处理程序的过程就称为“堆栈辗转开解”(Stack Unwinding)。解释器一方面维护着与放置堆栈中的函数有关的信息,另一方面也维护着与已从堆栈中“辗转开解”的函数有关的信息。

 
   try:
        block
    except:
        traceback.print_exc()


    四、采用sys模块回溯最后的异常

    import sys
    try:
        block
    except:
        info=sys.exc_info()
        print info[0],":",info[1]


或者以如下的形式:

   
import sys
        tp,val,td = sys.exc_info()

    sys.exc_info()的返回值是一个tuple, (type, value/message, traceback)
    这里的type是异常的类型,value/message是异常的信息或者参数,traceback包含调用栈信息的对象,从这点上可以看出此方法涵盖了traceback。

    以上都是错误处理的理论知识,接下来我们要动手设计一个自己的异常处理类,用来记录异常日志,将错误的日志按照每小时一个文件的频率,保存到我们指定的位置。代码如下:

    #coding:utf-8
    #基于python2.6
    import logging,os,time,traceback
    class LOG:
        def __init__(self,logger):
            self.fileHandlerName = ‘‘
            self.fileHandler = None
            self.loggerName = logger
            self.logger = logging.getLogger(logger)
            self.logger.setLevel(logging.DEBUG)
            self.formatter = logging.Formatter("=========================ntime:%(asctime)s nlogger:%(name)s nlevel:%(levelname)s nfile:%(filename)s nfun:%(funcName)s nlineno:%(lineno)d nmessage:%(message)s")
            # 控制台
            ch = logging.StreamHandler()
            ch.setLevel(logging.DEBUG)
            ch.setFormatter(self.formatter)
            self.logger.addHandler(ch)
            path = os.path.abspath(os.path.dirname(__file__)) + /log/+self.loggerName+/
            print log path=,path
       
        def setfh(self):
            fname = time.strftime("%Y%m%d%H")
            if fname!=self.fileHandlerName:
                #移除原来的句柄
                if self.fileHandler!=None :
                    self.logger.removeHandler(self.fileHandler)
                #设置日志文件保存位置
                path = os.path.abspath(os.path.dirname(__file__)) + /log/+self.loggerName+/
                print path
                if os.path.isdir(path) == False:
                    os.makedirs(path)
                fh = logging.FileHandler(path+fname+.log)
                fh.setLevel(logging.DEBUG)
                fh.setFormatter(self.formatter)
                self.logger.addHandler(fh)
                self.fileHandlerName = fname
                self.fileHandler = fh
        #格式化日志内容
        def _fmtInfo(self,msg):
            if len(msg)==0:
                msg = traceback.format_exc()
                return msg
            else:
                _tmp = [msg[0]]
                _tmp.append(traceback.format_exc())
                return n**********n.join(_tmp)
        #封装方法
        def debug(self,*msg):
            _info = self._fmtInfo(msg)
            try:
                self.setfh()
                self.logger.debug(_info)
            except:
                print mylog debug: + _info
        def error(self,*msg):
            _info = self._fmtInfo(msg)
            try:
                self.setfh()
                self.logger.error(_info)
            except:
                print mylog error: + _info
        def info(self,*msg):
            _info = self._fmtInfo(msg)
            try:
                self.setfh()
                self.logger.error(_info)
            except:
                print mylog info: + _info
        def warning(self,*msg):
            _info = self._fmtInfo(msg)
            try:
                self.setfh()
                self.logger.error(_info)
            except:
                print mylog warning: + _info
           
    if __name__==__main__:
        log = LOG(fight)
        try:
            print 1/0
        except:
            log.error() #使用系统自己的错误描述
        try:
            print 2/0
        except:
            log.error(搞错了,分母不能为0) #使用自己的错误描述
异常处理
1. 抛出异常和自定义异常
Python用异常对象(exception object)表示异常情况,遇到错误后,会引发异常。如果异常对象并未被处理或捕捉,程序就会用所谓的回溯(Traceback,一种错误信息)终止执行。
 
1.1 raise 语句
Python中的raise 关键字用于引发一个异常,基本上和C#和Java中的throw关键字相同,如下所示:
1 # -- coding: utf-8 --
2 
3 def ThorwErr():
4     raise Exception("抛出一个异常")
5 
6 # Exception: 抛出一个异常
7 ThorwErr() 

raise关键字后面是抛出是一个通用的异常类型(Exception),一般来说抛出的异常越详细越好,Python在exceptions模块内建了很多的异常类型,通过使用dir函数来查看exceptions中的异常类型,如下:
import exceptions
# [ArithmeticError, AssertionError.....]
print dir(exceptions)

 

传递异常
捕捉到了异常,但是又想重新引发它(传递异常),可以使用不带参数的raise语句即可:
 1 # -- coding: utf-8 --
 2 class MuffledCalculator:
 3     muffled = False
 4     def calc(self,expr):
 5         try:
 6             return eval(expr)
 7         except ZeroDivisionError:
 8             if self.muffled:
 9                 print Division by zero is illegal
10             else:
11                 raise

 
1.2 自定义异常类型
Python中也可以自定义自己的特殊类型的异常,只需要要从Exception类继承(直接或间接)即可:
class SomeCustomException(Exception):
    pass

 
2. 捕捉异常
和C#中的try/catch类似,Python中使用try/except关键字来捕捉异常,如下:
# -- coding: utf-8 --
try:
    print 2/0
except ZeroDivisionError:
    print 除数不能为02.1 捕捉多个异常
在一个except语句只捕捉其后声明的异常类型,如果可能会抛出的是其他类型的异常就需要再增加一个except语句了,或者也可以指定一个更通用的异常类型比如:Exception,如下:
# -- coding: utf-8 --
try:
    print 2/0
except ZeroDivisionError:
    print 除数不能为0
except Exception:
    print 其他类型异常

为了捕获多个异常,除了声明多个except语句之外,还可以在一个except语句之后将多个异常作为元组列出来即可:
# -- coding: utf-8 --
try:
    print 2/0
except (ZeroDivisionError,Exception):
    print 发生了一个异常

 
2.2获取异常信息
每个异常都会有一些异常信息,一般情况下我们应该把这些异常信息记录下来:
# -- coding: utf-8 --
try:
    print 2/0
except (ZeroDivisionError,Exception) as e:
    # unsupported operand type(s) for /: int and str
    print e 


 
3. finally子句
finally子句和try子句联合使用但是和except语句不同,finally不管try子句内部是否有异常发生,都会执行finally子句内的代码。所有一般情况下,finally自己常常用于关闭文件或者在Socket中。
# -- coding: utf-8 --
try:
    print 2/0
except (ZeroDivisionError,Exception):
    print 发生了一个异常
finally:
    print 不管是否发生异常都执行

 

  之前在学习python的时候有整理过python异常处理的文章,不够简单也不够完整,所以决定再整理一篇,算做补充。
http://www.cnblogs.com/fnng/archive/2013/04/28/3048356.html

python shell
>>> open(abc.txt,r)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: abc.txt

  打开一个不存在的文件abc.txt 文件,当系统找不到abc.txt 文件时,就会抛出给我们一个IOError类型的错误,No such file or directory:abc.txt (没有abc.txt这样的文件或目录)

Try...except...
  假如,我们已经知道这种类型的错误,那么就可以通过一个异常扑捉来扑捉这个错误。我们可以通过try...except 来接收这个错误。打开文件写入:
try:
    open("abc.txt",r)
except IOError:
    pass 
   再来运行程序就会看不到任何错误,因为我们用except 接收了这个IOError错误。pass 表示实现了相应的实现,但什么也不做。

  假如我不是打开一个文件,而是输出一个没有定义的变量呢? 
try:
    print  aa
except IOError:
    pass 

显然,在上面的代码中我并没有对aa 赋值,运行结果:

Traceback (most recent call last):
  File "/home/fnngj/py_se/tryy.py", line 3, in <module>
    print  aa
NameError: name aa is not defined

  我们已经用except 接收错误了,为什么错误还是还是抛出来了。如果你细心会发现这一次的错误类型是NameError ,而我接收类型是IOError ,所以要想接收这个print的错误,那么需要修改接收错误的类型为NameError

  虽然,我知道print 语句是可能会抛一个NameError 类型的错误,虽然接收了这个类型错误,但我不知道具体的错误提示信息是什么。那么,我能不能把错误信息打印出来呢?当然可以:
try:
    print  aa
except  NameError, msg:
    print  msg
  我们在接收错误类型的后面定义一个变量msg用于接收具体错误信息, 然后将msg接收的错误信息打印。再来运行程序:
name aa is not defined
现在只打印了一行具体错误信息。

异常的抛出机制:
1、如果在运行时发生异常,解释器会查找相应的处理语句(称为handler).
2、要是在当前函数里没有找到的话,它会将异常传递给上层的调用函数,看看那里能不能处理。
3、如果在最外层(全局“main”)还是没有找到的话,解释器就会退出,同时打印出traceback以便让用户找到错误产生的原因。


注意:虽然大多数错误会导致异常,但一个异常不一定代表错误,有时候它们只是一个警告,有时候它们可能是一个终止信号,比如退出循环等。


try...finally...
try...finally...子句用来表达这样的情况:
我们不管线捕捉到的是什么错误,无论错误是不是发生,这些代码“必须”运行,比如文件关闭,释放锁,把数据库连接返还给连接池等。 

创建文件poem.txt
tryf.py
import time
try:
    f = file(poem.txt)
    while True: # our usual file-reading idiom
        line = f.readline()
        if len(line) == 0:
            break
        time.sleep(2)
        print line,
finally:
    f.close()
    print Cleaning up...closed the file

运行程序(在windows命令提示符或linux终端下运行):
...$ python tryf.py 
abc
efg
^CCleaning up...closed the file
Traceback (most recent call last):
  File "tryy.py", line 18, in <module>
    time.sleep(2)
KeyboardInterrupt

  程序读poem.txt文件中每一行数据打印,但是我有意在每打印一行之前用time.sleep方法暂停2秒钟。这样做的原因是让程序运行得慢一些。在程序运行的时候,按Ctrl-c中断/取消程序。
  我们可以观察到KeyboardInterrupt异常被触发,程序退出。但是在程序退出之前,finally从句仍然被执行,把文件关闭。


到目前为止,我们只讨论了如何捕捉异常,那么如何抛出异常呢?

Raise抛出异常

 
使用raise来抛出一个异常:
tryr.py
#coding=utf-8
filename = raw_input(please input file name:)
if filename==hello:
    raise NameError(input file name error !)

  程序要求用户输入一个文件名,如果用户输入的文件名是hello ,那么抛出一个NameError的异常,用户输入hello 和NameError异常之间没有任何必然联系,我只是人为的通过raise来这样定义,我当然也可以定义称TypeError ,但我定义的异常类型必须是python提供的。
 

附录:
常见的python异常类型

 

当你的程序中出现异常情况时就需要异常处理。比如当你打开一个不存在的文件时。当你的程序中有一些无效的语句时,Python会提示你有错误存在。

下面是一个拼写错误的例子,print写成了Print。Python是大小写敏感的,因此Python将引发一个错误:
>>> Print ‘Hello World‘
    File "", line 1
      Print ‘Hello World‘
                        ^
SyntaxError: invalid syntax

>>> print ‘Hello World‘
Hello World

1、try...except语句

try...except语句可以用于捕捉并处理错误。通常的语句放在try块中,错误处理语句放在except块中。示例如下:
#!/usr/bin/python
# Filename: try_except.py

import sys

try:
	s = raw_input(‘Enter something --> ‘)
except EOFError:#处理EOFError类型的异常
	print ‘/nWhy did you do an EOF on me?‘
	sys.exit() # 退出程序
except:#处理其它的异常
	print ‘/nSome error/exception occurred.‘
	
print ‘Done‘
运行输出如下:
$ python try_except.py
Enter something -->
Why did you do an EOF on me?

$ python try_except.py
Enter something --> Python is exceptional!
Done
说明:每个try语句都必须有至少一个except语句。如果有一个异常程序没有处理,那么Python将调用默认的处理器处理,并终止程序且给出提示。

2、引发异常

你可以用raise语句来引发一个异常。异常/错误对象必须有一个名字,且它们应是Error或Exception类的子类。
下面是一个引发异常的例子:
#!/usr/bin/python
#文件名: raising.py

class ShortInputException(Exception):
	‘‘‘你定义的异常类。‘‘‘
	def __init__(self, length, atleast):
		Exception.__init__(self)
		self.length = length
		self.atleast = atleast

try:
	s = raw_input(‘请输入 --> ‘)
	if len(s) < 3:
		raise ShortInputException(len(s), 3)
	# raise引发一个你定义的异常
except EOFError:
	print ‘/n你输入了一个结束标记EOF‘
except ShortInputException, x:#x这个变量被绑定到了错误的实例
	print ‘ShortInputException: 输入的长度是 %d, /
		长度至少应是 %d‘ % (x.length, x.atleast)
else:
	print ‘没有异常发生.‘
运行输出如下:
$ python raising.py
请输入 -->
你输入了一个结束标记EOF

$ python raising.py
请输入 --> --> ab
ShortInputException: 输入的长度是 2, 长度至少应是 3

$ python raising.py
请输入 --> abc
没有异常发生.

3、try...finally语句

当你正在读文件或还未关闭文件时发生了异常该怎么办呢?你应该使用try...finally语句以释放资源。示例如下:
运行输出如下:
$ python finally.py
Programming is fun
When the work is done
Cleaning up...closed the file
Traceback (most recent call last):
  File "finally.py", line 12, in ?
    time.sleep(2)
KeyboardInterrupt

说明:我们在两秒这段时间内按下了Ctrl-c,这将产生一个KeyboardInterrupt异常,我们并没有处理这个异常,那么Python将调用默认的处理器,并终止程序,在程序终止之前,finally块中的语句将执行。

 

 

 

 

 

技术分享

 

 

 

python中的异常

异常是指程序中的例外,违例情况。异常机制是指程序出现错误后,程序的处理方法。当出现错误后,程序的执行流程发生改变,程序的控制权转移到异常处理。
Exception类是常用的异常类,该类包括StandardError,StopIteration, GeneratorExit, Warning等异常类。
StandardError类是python中的错误异常,如果程序上出现逻辑错误, 将引发该异常。StandardError类是所有内敛异常的基类,放置在默认的命名空间中,因此使用IOEroor, 
EOFError, ImportError等类,不需要导入exception模块。
StopIteration类判断循环是否执行到尾部,如果循环到尾部,则抛出该异常。
GeneratorExit类是由Generator函数引发的异常,当调用close()时引发该异常。
Warning类表示程序中的代码引起的警告。
python中的异常使用继承结构创建,可以在异常处理程序中捕获基类异常,也可以捕获各种子类异常,python中使用try...except语句捕获异常,异常子句定义在try子句后面。

try...except的使用方法

try...except用于处理问题语句,捕获可能出现的异常。try子句中的代码块放置可能出现异常的语句,except子句中的代码块处理异常。
演示try...except语句捕获IOError异常
try:
     file("hello.txt", "r")                  #如果文件不存在,引发异常
     print "读文件"
except IOError:                              #捕获IO异常
     print "文件不存在"
except:                                     #其它异常
     print "程序异常" 

python与Java的异常处理模式相似,异常处理语句也可以嵌套,演示如下:
try:
     s = "hello"
     try:
          print s[0] + s[1]
          print s[0] - s[1]
     except TypeError:
          print "字符串不支持减法运算"
except:
     print "异常"
如果外层try子句中的代码引发异常,程序将直接跳转到外层try对应的except子句,而内部的try子句将不会被执行。

try...finally的使用方法
try...except后还可以添加一个finally子句。无论异常是否发生,finally子句都会被执行。所有的finally子句通常用于关闭因异常而不能释放的系统资源。
try:
     f = open("hello.txt", "r")
     try:
          print f.read(5)
     except:
          print "读文件异常"
     finally:
          print "释放资源"
          f.close()
except IOError:
     print "文件不存在"

使用raise抛出异常
当程序出现错误,python会自动引发异常,也可以通过raise显示地引发异常。一旦执行了raise语句,raise后面的语句将不能执行。
演示raise用法
try:
     s = None
     if s is None:
         print "s 是空对象"
         raise NameError     #如果引发NameError异常,后面的代码将不能执行
     print len(s)
except TypeError:
     print "空对象没有长度"

自定义异常
python允许程序员自定义异常,用于描述python中没有涉及的异常情况,自定义异常必须继承Exception类,自定义异常按照命名规范以"Error"结尾,显示地告诉程序员这是异常。自定义异常使用raise语句引发,而且只能通过人工方式触发。
from __future__ import division

class DivisionException(Exception):
      def __init__(self, x, y):
            Exception.__init__ (self, x, y)       #调用基类的__init__进行初始化
            self.x = x
            self.y = y

if __name__ == "__main__":
      try:
            x = 3
            y = 2
      if x % y > 0:                               #如果大于0, 则不能被初始化,抛出异常
            print x/y
            raise DivisionException(x, y)
except DivisionException,div:                     #div 表示DivisionException的实例对象
      print "DivisionExcetion: x/y = %.2f" % (div.x/div.y)

assert语句的使用
assert语句用于检测某个条件表达式是否为真。assert语句又称为断言语句,即assert认为检测的表达式永远为真,if语句中的条件判断都可以使用assert语句检测。

 

python异常处理

标签:

原文地址:http://www.cnblogs.com/x113/p/4703609.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!