python异常处理

1、异常简介

从软件方面来说,错误是语法或是逻辑上的,当python检测到一个错误时,解释器就会指出当前流已经无法继续执行下去,这时候就出现了异常。异常分为两个阶段:首先是引起异常发生的错误,然后是检测和采取可能的措施。常见异常有NameError、ZeroDivisionError、SyntaxError、IndexError、KeyError、IOError、AttributeError、ValueError、TypeError等。所有的标准/内建异常都是从根异常派生的,目前,有3个直接从BaseException派生的异常子类:SystemExit,KeyboardInterrupt和Exception。其它的所有的内建异常都是Exception的子类。

2、异常检测及处理

异常可以通过try语句来检测,有两种主要形式:try-except和try-finally。前者可以添加一个可选的else子句来处理没有检测到异常的情况。一个try语句可以对应一个或多个except语句,但只能对应一个finally子句,except用来捕获并处理异常,可以处理多个异常,也可以指定可选的异常参数(将会是一个包含来自异常的代码的诊断信息的类实例,异常参数自身会组成一个元组,并存储为类实例的属性),要避免裸except(会捕获所有异常,没有机会保存异常发生的原因,虽然可以通过sys.exc_info()获得,但不推荐,如果想捕获所有异常,可以在except中使用BaseException类,而Exception类不包括KeyboardInterrupt和SystemExit),finally无论发生错误与否都会执行。try-except-finally是个复合语句。try检测到异常时,try语句块中的剩余代码是不会执行的,异常会延着堆栈向上提交,直到找到合适的异常处理器,如果到达最顶层仍然没有找到对应的处理器,python解释器会显示出跟踪返回消息,然后退出。

Python用异常对象(exception object)表示异常情况,遇到错误后,会引发异常。如果异常对象并未被处理或捕捉,程序就会用所谓的回溯(Traceback,一种错误信息)终止执行。

try 语句的工作原理如下。

  • 首先,执行 try 子句tryexcept 关键字之间的(多行)语句)。
  • 如果没有异常发生,则跳过 except 子句 并完成 try 语句的执行。
  • 如果在执行try 子句时发生了异常,则跳过该子句中剩下的部分。然后,如果异常的类型和 except 关键字后面的异常匹配,则执行 except 子句 ,然后继续执行 try 语句之后的代码。
  • 如果发生的异常和 except 子句中指定的异常不匹配,则将其传递到外部的 try 语句中;如果没有找到处理程序,则它是一个 未处理异常,执行将停止并显示如上所示的消息。
try: 
  try_suite 
except Exception1[, reason1]: 
  suite_for_exception_ Exception1 
except Exception2[, reason2]: 
  suite_for_exception_ Exception2 
except (Exception3, Exception4)[, reason3_4]: 
  suite_for_exceptions_ Exception3_and_Exception4 
except (Exc5[, Exc6[, ... ExcN]])[, reason]: 
  suite_for_exceptions_ Exc5_to_ExcN 
else: 
  suite_for_no_exception 
finally: 
  suite_always_run 

可同时捕捉多个异常,可捕捉异常对象,可忽略异常类型以捕捉所有异常

>>> try: 
  x = int(input('input x:')) 
  y = int(input('input y:')) 
  print('x/y = ',x/y) 
except ZeroDivisionError: #捕捉除0异常 
  print("ZeroDivision") 
except (TypeError,ValueError) as e: #捕捉多个异常,并将异常对象输出 
  print(e) 
except: #捕捉其余类型异常 
  print("it's still wrong") 
  
    
input x:12
input y:0
ZeroDivision 
>>> try: 
  x = int(input('input x:')) 
  y = int(input('input y:')) 
  print('x/y = ',x/y) 
except ZeroDivisionError: #捕捉除0异常 
  print("ZeroDivision") 
except (TypeError,ValueError) as e: #捕捉多个异常,并将异常对象输出 
  print(e) 
except: #捕捉其余类型异常 
  print("it's still wrong") 
  
    
input x:12
input y:y 
invalid literal for int() with base 10: 'y'

try/except 可以加上 else 语句,实现在没有异常时执行什么

>>> try: 
  x = int(input('input x:')) 
  y = int(input('input y:')) 
  print('x/y = ',x/y) 
except ZeroDivisionError: #捕捉除0异常 
  print("ZeroDivision") 
except (TypeError,ValueError) as e: #捕捉多个异常 
  print(e) 
except: #捕捉其余类型异常 
  print("it's still wrong") 
else: #没有异常时执行 
  print('it work well') 
  
    
input x:12
input y:3
x/y = 4.0
it work well 

2. 捕捉异常

为了处理异常,我们使用try...except

把可能发生错误的语句放在try模块里,用except来处理异常。

except可以处理一个专门的异常,也可以处理一组圆括号中的异常,如果except后没有指定异常,则默认处理所有的异常。

每一个try,都必须至少有一个except

在python的异常中,有一个万能异常:Exception,他可以捕获任意异常

s1 = 'hello'
try:
  int(s1)
except Exception,e:
  print e

程序时需要考虑到try代码块中可能出现的多个异常,可以这样写:

s1 = 'hello'
try:
  int(s1)
except IndexError,e:
  print e
except KeyError,e:
  print e
except ValueError,e:
  print e

异常的简单结构和复杂结构

try:
  pass
except Exception as e: #python2 中还可以这样写:except Exception,e
  pass

try 语句子句形式表

except: 捕获所有异常

except name: 只捕获特定的异常

except name,value: 捕获异常和它的附加数据(将异常的信息保存到value,)

except (name1,name2): 捕获任何列出的异常

else: 如果没有异常

finally: 总是执行

先定义特殊提醒的异常,最后定义Exception,来确保程序正常运行。

先特殊,后万能

s1 = 'hello'
try:
  int(s1)
except KeyError,e:
  print '键错误'
except IndexError,e:
  print '索引错误'
except Exception, e:
  print '错误'

①.捕捉多个异常

在一个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 '发生了一个异常'

②.获取异常信息

每个异常都会有一些异常信息,一般情况下我们应该把这些异常信息记录下来:

# -- coding: utf-8 --
try:
  print 2/'0'
except (ZeroDivisionError,Exception) as e:
  # unsupported operand type(s) for /: 'int' and 'str'
  print e

3.自定义异常:

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

class myException(Exception):pass
class WupeiqiException(Exception):
  
  def __init__(self, msg):
    self.message = msg
  
  def __str__(self):
    return self.message
  
try:
  raise WupeiqiException('我的异常')
except WupeiqiException,e:
  print e

4.抛出异常和传递异常:

Python中的raise 关键字用于引发一个异常,基本上和C#和Java中的throw关键字相同。

>>> def division(x,y): 
  if y == 0 : 
    raise ZeroDivisionError('The zero is not allow') 
  return x/y 
  
>>> try: 
  division(1,0) 
except ZeroDivisionError as e: 
  print(e) 
  
    
The zero is not allow 

一般来说,raise关键字后面抛出的异常越详细越好,Python在exceptions模块内建了很多的异常类型,通过使用dir函数来查看exceptions中的异常类型,如下:

import exceptions
 
# ['ArithmeticError', 'AssertionError'.....]
print dir(exceptions)

传递异常,即捕捉到了异常,但是又想重新引发它(传递异常),可以使用不带参数的raise语句即可:

# -- coding: utf-8 --
class MuffledCalculator:
  muffled = False
  def calc(self,expr):
    try:
      return eval(expr)
    except ZeroDivisionError:
      if self.muffled:
        print 'Division by zero is illegal'
      else:
        raise

主动触发异常

raise Exception('messages') 可以自定义报错信息

a=2
if a > 1:
  raise ValueError('值大于1')

raise 触发异常

try:
  raise Exception('错误了。。。')
except Exception,e:
  print e

5.finally 语句

不管是否出现异常,最后都会执行finally的语句块内容,用于清理工作

所以,你可以在 finally 语句中关闭文件,这样就确保了文件能正常关闭

finally子句和try子句联合使用但是和except语句不同,finally不管try子句内部是否有异常发生,都会执行finally子句内的代码。所有一般情况下,finally自己常常用于关闭文件或者在Socket中。

>>> try: 
  x = int(input('input x:')) 
  y = int(input('input y:')) 
  print('x/y = ',x/y) 
except ZeroDivisionError: #捕捉除0异常 
  print("ZeroDivision") 
except (TypeError,ValueError) as e: #捕捉多个异常 
  print(e) 
except: #捕捉其余类型异常 
  print("it's still wrong") 
else: #没有异常时执行 
  print('it work well') 
finally: #不管是否有异常都会执行 
  print("Cleaning up") 
  
    
input x:12
input y:3
x/y = 4.0
it work well 
Cleaning up 

异常抛出之后,如果没有被接收,那么程序会抛给它的上一层,比如函数调用的地方,要是还是没有接收,那继续抛出,如果程序最后都没有处理这个异常,那它就丢给操作系统了 -- 你的程序崩溃了,这点和C++一样的。

注意:你可以使用except语句或者finally语句,但是两者不能同时使用。else语句也不能与finally语句同时使用

在else块是不需要try:块的代码的保护。

6.python标准异常

在 Python 中,所有异常必须为一个派生自 BaseException 的类的实例。 通过子类化创建的两个不相关异常类永远是不等效的,既使它们具有相同的名称。

下列异常主要被用作其他异常的基类。

BaseException: 所有异常的基类

Exception(重点掌握)

所有内置的非系统退出类异常都派生自此类。 所有用户自定义异常也应当没打算自此类。

ArithmeticError

此基类用于派生针对各种算术类错误而引发的内置异常: OverflowError, ZeroDivisionError, FloatingPointError。

BufferError

当与 缓冲区 相关的操作无法执行时将被引发。

LookupError

此基类用于派生当映射或序列所使用的键或索引无效时引发的异常: IndexError, KeyError

内置异常的层次结构

BaseException       所有异常的基类     
 +-- SystemExit       解释器请求退出
 +-- KeyboardInterrupt     用户中断执行(通常是输入^C)
 +-- GeneratorExit      生成器(generator)发生异常来通知退出
 +-- Exception        常规错误的基类
   +-- StopIteration       迭代器没有更多值 
   +-- StopAsyncIteration       必须通过异步迭代器对象的__anext__()方法引发以停止迭代
   +-- ArithmeticError         所有数值计算错误的基类
   |  +-- FloatingPointError       浮点计算错误
   |  +-- OverflowError         数值运算超出最大限制
   |  +-- ZeroDivisionError       除(或取模)零 (所有数据类型
   +-- AssertionError         断言语句失败
   +-- AttributeError         对象没有这个属性
   +-- BufferError          与缓冲区相关的操作时引发
   +-- EOFError            没有内建输入,到达EOF 标记
   +-- ImportError           导入失败
   |  +-- ModuleNotFoundError    找不到模块
   +-- LookupError           无效数据查询的基类
   |  +-- IndexError           序列中没有此索引(index)
   |  +-- KeyError            映射中没有这个键
   +-- MemoryError           内存溢出错误
   +-- NameError            未声明、初始化对象
   |  +-- UnboundLocalError       访问未初始化的本地变量
   +-- OSError             操作系统错误,
   |  +-- BlockingIOError        操作将阻塞对象设置为非阻塞操作
   |  +-- ChildProcessError       子进程上的操作失败
   |  +-- ConnectionError        与连接相关的异常的基类
   |  |  +-- BrokenPipeError       在已关闭写入的套接字上写入
   |  |  +-- ConnectionAbortedError   连接尝试被对等方中止
   |  |  +-- ConnectionRefusedError   连接尝试被对等方拒绝
   |  |  +-- ConnectionResetError    连接由对等方重置
   |  +-- FileExistsError        创建已存在的文件或目录
   |  +-- FileNotFoundError       请求不存在的文件或目录
   |  +-- InterruptedError       系统调用被输入信号中断
   |  +-- IsADirectoryError       在目录上请求文件操作
   |  +-- NotADirectoryError      在不是目录的事物上请求目录操作
   |  +-- PermissionError       在没有访问权限的情况下运行操作
   |  +-- ProcessLookupError      进程不存在
   |  +-- TimeoutError         系统函数在系统级别超时
   +-- ReferenceError        弱引用试图访问已经垃圾回收了的对象
   +-- RuntimeError         一般的运行时错误
   |  +-- NotImplementedError   尚未实现的方法
   |  +-- RecursionError      解释器检测到超出最大递归深度
   +-- SyntaxError          Python 语法错误
   |  +-- IndentationError     缩进错误
   |     +-- TabError     Tab 和空格混用
   +-- SystemError       一般的解释器系统错误
   +-- TypeError        对类型无效的操作
   +-- ValueError       传入无效的参数
   |  +-- UnicodeError       Unicode 相关的错误
   |     +-- UnicodeDecodeError   Unicode 解码时的错误
   |     +-- UnicodeEncodeError   Unicode 编码时错误
   |     +-- UnicodeTranslateError Unicode 转换时错误
   +-- Warning            警告的基类
      +-- DeprecationWarning     关于被弃用的特征的警告
      +-- PendingDeprecationWarning  关于构造将来语义会有改变的警告
      +-- RuntimeWarning      可疑的运行行为的警告
      +-- SyntaxWarning      可疑的语法的警告
      +-- UserWarning       用户代码生成的警告
      +-- FutureWarning      有关已弃用功能的警告的基类
      +-- ImportWarning      模块导入时可能出错的警告的基类
      +-- UnicodeWarning      与Unicode相关的警告的基类
      +-- BytesWarning       bytes和bytearray相关的警告的基类
      +-- ResourceWarning      与资源使用相关的警告的基类
异常名称描述
  
BaseException所有异常的基类
SystemExit解释器请求退出
KeyboardInterrupt用户中断执行(通常是输入^C)
Exception常规错误的基类
StopIteration迭代器没有更多的值
GeneratorExit生成器(generator)发生异常来通知退出
SystemExitPython 解释器请求退出
StandardError所有的内建标准异常的基类
ArithmeticError所有数值计算错误的基类
FloatingPointError浮点计算错误
OverflowError数值运算超出最大限制
ZeroDivisionError除(或取模)零 (所有数据类型)
AssertionError断言语句失败
AttributeError对象没有这个属性
EOFError没有内建输入,到达EOF 标记
EnvironmentError操作系统错误的基类
IOError输入/输出操作失败
OSError操作系统错误
WindowsError系统调用失败
ImportError导入模块/对象失败
KeyboardInterrupt用户中断执行(通常是输入^C)
LookupError无效数据查询的基类
IndexError序列中没有没有此索引(index)
KeyError映射中没有这个键
MemoryError内存溢出错误(对于Python 解释器不是致命的)
NameError未声明/初始化对象 (没有属性)
UnboundLocalError访问未初始化的本地变量
ReferenceError弱引用(Weak reference)试图访问已经垃圾回收了的对象
RuntimeError一般的运行时错误
NotImplementedError尚未实现的方法
SyntaxErrorPython 语法错误
IndentationError缩进错误
TabErrorTab 和空格混用
SystemError一般的解释器系统错误
TypeError对类型无效的操作
ValueError传入无效的参数
UnicodeErrorUnicode 相关的错误
UnicodeDecodeErrorUnicode 解码时的错误
UnicodeEncodeErrorUnicode 编码时错误
UnicodeTranslateErrorUnicode 转换时错误
Warning警告的基类
DeprecationWarning关于被弃用的特征的警告
FutureWarning关于构造将来语义会有改变的警告
OverflowWarning旧的关于自动提升为长整型(long)的警告
PendingDeprecationWarning关于特性将会被废弃的警告
RuntimeWarning可疑的运行时行为(runtime behavior)的警告
SyntaxWarning可疑的语法的警告
UserWarning用户代码生成的警告
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值