Python学习7——异常

编写程序时,通常能够区分正常和异常情况。为了处理这些异常,可在每个可能出现异常的地方都使用上条件语句,但这样大大降低了程序的可读性,那么怎么解决哪?Python提供强大的替代解决方案——异常处理机制

1、异常是什么?

Python使用异常对象来表示异常状态,并在遇到错误时引发异常,异常对象未被处理(或捕获)时,程序将终止并显示一条错误消息。

>>> 1/0
Traceback (most recent call last):
  File "<pyshell#214>", line 1, in <module>
    1/0
ZeroDivisionError: division by zero

2、让事情沿着指定的轨道出错

2.1 raise语句

要引发异常,可使用raise语句,并将一个类(必须是Exception的子类)或实例作为参数。将类作为参数时,将自动创建一个实例。

>>> raise Exception
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    raise Exception
Exception
#上方引发的是通用异常,没有指出出现了什么错误
>>> raise Exception(‘hyperdrive overload‘)
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    raise Exception(‘hyperdrive overload‘)
Exception: hyperdrive overload
#上方示例添加了错误消息hyperdrive overload

下方给出一些常用到的内置的异常类

类名 描述
Exception 几乎所有的异常类都是从它派生而来的
AttributeError 引用属性或者给它赋值失败时引发
OSError 操作系统不能执行指定任务时(如打开文件)引发,有多个子类
IndexError 使用序列中不存在的索引时引发,为LookuoError的子类
keyError 使用映射中不存在的键时引发,为LookupError的子类
NameError 找不到名称(变量)时引发
syntaxError 代码不正确时引发
TypeError 将内置操作或函数用于类型不正确的对象时引发
ValueError 将内置操作或者函数用于这样的对象时引发:其类型正确担包含的值不合适
ZeroDivisionError 在除法或者求模运算中的第二个参数为零时引发

2.2自定义的异常类

虽然内置异常类的范围足够广泛,但有的时候你可能想要自己创建异常类满足自己的代码需要。

那么如何创建自定义异常类哪?

就像创建其他类一样,不过必须直接或间接的继承Exception

>>>class someException(Exception):
    pass
#当然,如果你乐意,也可以在自定义异常类中添加方法

3、捕获异常

try:
    x=int(input("Please input x:"))
    y=int(input("Please input y:"))
    print(x/y)
except ZeroDivisionError:
        print("The second numbercna‘t be zero!")
#一定要注意代码的缩进问题

Please input x:1
Please input y:0
The second numbercna‘t be zero!

3.1不用提供参数

捕获异常之后,如果要重新引发它(即继续向上传播),可调用raise契额不提供任何参数(也可显式地提供捕获到的异常,参见3.4).

这很有用,我们下面看一个例子:

>>> class MuffledCalculator:
    mufflad=False
    def calc(self,expr):
        try:
            return eval(expr)
        except ZeroDivisionError:
            if self.mufflad:
                print("Division by zero is illegal")
            else:
                raise
#发生除零行为时,如果启用了“抑制”功能,方法cacl将(隐式地)返回None。换而言之,如果启用了“抑制”功能,就不应依赖返回值。

>>> calculator=MuffledCalculator()
>>> calculator.calc(‘10/2‘)
5.0
>>> calculator.calc(‘10/0‘)#关闭了抑制功能
Traceback (most recent call last):
  File "<pyshell#20>", line 1, in <module>
    calculator.calc(‘10/0‘)
  File "<pyshell#17>", line 5, in calc
    return eval(expr)
  File "<string>", line 1, in <module>
ZeroDivisionError: division by zero

>>> calculator.mufflad=True
>>> calculator.calc(‘10/0‘)
Division by zero is illegal

如你所见,关闭抑制功能时,捕获了异常 ZeroDivisionError 但继续向上传播它。

如果无法处理异常,在Except子句中使用不带参数的raise通常是不错的选择,但有时你可能想引发别的异常。在这种情况下,导致进入except子句的异常将被作为异常上下文存储起来,并出现在最终的错误消息中,如下所示:

>>> try:
    1/0
except ZeroDivisionError:
    raise ValueError

Traceback (most recent call last):
  File "<pyshell#27>", line 2, in <module>
    1/0
ZeroDivisionError: division by zero
#在处理上述异常时引发了另一个异常
During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#27>", line 4, in <module>
    raise ValueError
ValueError

你可以使用raise...from...语句来提供自己的异常上下文,也可以使用None来禁用上下文。

>>> try:
    1/0
except ZeroDivisionError:
    raise ValueError from None

Traceback (most recent call last):
  File "<pyshell#32>", line 4, in <module>
    raise ValueError from None
ValueError
>>> 

3.2多个except语句

‘
>>> try:
    x=int(input("Please input x:"))
    y=int(input("Please input y:"))
    print(x/y)
except ZeroDivisionError:
        print("The second numbercna‘t be zero!")
except ValueError:
    print("That wasn‘t a number ,was it?")

Please input x:1
Please input y:0
The second numbercna‘t be zero!

Please input x:1
Please input y:e
That wasn‘t a number ,was it?
>>> 

3.3一箭多雕

使用一个except 语句捕获多种异常,将异常类放在一个元组里。

>>> try:
    x=int(input("Please input x:"))
    y=int(input("Please input y:"))
    print(x/y)
except (ZeroDivisionError,ValueError):
        print("The numbers you input have bugs!")

Please input x:1
Please input y:0

Please input x:3
Please input y:d
The numbers you input have bugs!

3.4捕获对象

要在except 语句中访问异常对象本身,可使用两个参数而不是一个参数(即便是你捕获多个异常时,也只是向except 提供了一个参数——一个元组。)需要让程序继续运行并记录错误(可能只是向用户显示)时,这很有用。下面这个示例,程序打印出现的异常并继续运行:

>>> try:
    x=int(input("Please input x:"))
    y=int(input("Please input y:"))
    print(x/y)
except (ZeroDivisionError,ValueError)as e:
        print(e)

Please input x:1
Please input y:0
division by zero

Please input x:1
Please input y:r
invalid literal for int() with base 10: ‘r‘

3.5一网打尽

即使程序处理了很多异常,但还是有漏网之鱼,例如上面程序什么都不输入就按回车键,仍然会出现一条错误信息,还有一些相关问题出现在什么地方的信息(栈跟踪),如下所示:

Please input x:
invalid literal for int() with base 10: ‘‘

这种异常没有被捕捉到,因为你根本就没有预料这种情况,那这么做那?

>>> try:
    x=int(input("Please input x:"))
    y=int(input("Please input y:"))
    print(x/y)
except :
        print("Something wrong happened...")

这样更不行了,因为这不仅会隐藏你预料到的错误,更隐藏了你根本就没有想到的异常,你根本不知道哪出错了。。。

在大多数情况下,更好的选择是使用except Exceeption as e 并对异常对象进行检查。

3.6万事大吉时

有时候,在没有出现异常时执行一个代码块很有用。为此可以给try except语句加一个else语句。

同时,通过使用else 语句可以实现循环效果。

最后还有finally子句,可用在发生异常时执行清理作用。这个子句是和try子句配套的。

不管try子句中发生什么异常,都将执行finally子句

>>> while True :
    try:
        x=int(input("entern the x:"))
        y=int(input("entern the y:"))
        value=x/y
        print("x/y is ",value)
    except Exception as e:
        print("Invalid input:",e)
        print("Please try again")
    else :
        break
    finally:
        print("Everything is OK!")

entern the x:1
entern the y:0
Invalid input: division by zero
Please try again
Everything is OK!
entern the x:1
entern the y:2
x/y is  0.5
Everything is OK!

4、异常和函数

函数和异常有着天然的联系,如果不处理函数中引发的异常,它将会向上传播到调用函数的地方。如果在那里也未得到处理,将会继续传播,直至到达主程序(全局作用域),如果主程序也不处理,那么程序将会终止并显示栈跟踪信息。下面看一个例子:

>>> def faulty():
    raise Exception(‘Something is wrong‘)

>>> def ignore_exception():
    faulty()

>>> def handle_exception():
    try:
        faulty()
    except:
        print("Exception handle")

>>> ignore_exception()
Traceback (most recent call last):
  File "<pyshell#39>", line 1, in <module>
    ignore_exception()
  File "<pyshell#30>", line 2, in ignore_exception
    faulty()
  File "<pyshell#27>", line 2, in faulty
    raise Exception(‘Something is wrong‘)
Exception: Something is wrong
>>> handle_exception()
Exception handle

如你所见,faulty引发的异常依次从faulty和ignore_exception向外传播,最终导致显示一条栈跟踪消息。

调用handle_exception时,异常最终传播到handle_exception,并被这里的try/except语句处理。

5、异常之禅

异常处理并不复杂

6、只是警告(此处会用到几个函数,你可能不理解,但后面会介绍新学的函数)

有的时候,你只是想发出警告,指出情况偏离了正轨,可以使用warnings中的函数warn

>>> from warnings import warn
>>> warn("I‘ve got a bad feeling about this.")

Warning (from warnings module):
  File "__main__", line 1
UserWarning: I‘ve got a bad feeling about this.
#警告只显示一次,如果再次运行最后一行代码,将什么都不显示

如果其他代码在使用你的模块,可使用模块warnings 中的函数filterwarnings来抑制你发出的警告(或特定类型的警告),并指定要采取的措施,如"error"或者"ignore"

>>> from warnings import filterwarnings
>>> filterwarnings(‘ignore‘)
>>> warn(‘Anyone out there‘)
>>> filterwarnings("error")
>>> warn("Something is very wrong!")
Traceback (most recent call last):
  File "<pyshell#49>", line 1, in <module>
    warn("Something is very wrong!")
UserWarning: Something is very wrong!

如你所见,引发的异常为UserWarning,发出警告时,可指定将引发的异常(即警告类别),但必须是Warning的子类。

如果将警告转换为错误,将使用你指定的异常。

另外,还可根据异常来过滤掉特定类型的警告:

>>> filterwarnings("error")
>>> warn("This function is really old ......",DeprecationWarning)
Traceback (most recent call last):
  File "<pyshell#59>", line 1, in <module>
    warn("This function is really old ......",DeprecationWarning)
DeprecationWarning: This function is really old ......

>>> filterwarnings("ignore",category=DeprecationWarning)
>>> warn("Another deprecation warning.",DeprecationWarning)
>>> warn("Something else.")
Traceback (most recent call last):
  File "<pyshell#63>", line 1, in <module>
    warn("Something else.")
UserWarning: Something else.
>>> 

小结:异常对象、引发异常、自定义的异常类、捕获异常、else子句、finally子句、异常和函数、警告

本节新学习的函数
函数 描述
warnings.filterwarnings(action,category=Warning,...) 用于过滤警告
warnings.warn(message,category=None) 用来发出警告

原文地址:https://www.cnblogs.com/jiameng991010/p/11240364.html

时间: 2024-10-10 09:52:39

Python学习7——异常的相关文章

Python学习 之 异常

1.python中处理异常的方式 #coding:utf8 filename=raw_input("请输入你要操作的文件") try: f=open(filename) print 'hello' except IOError,msg: print "你指定的文件不存在" except NameError,msg: print "内部变量调用错误" finally: #finally try: #异常嵌套 f.close() except Nam

Python学习笔记-异常

Python的运行时错误称为异常 1.语法错误:软件的结构上有错误而导致不能被解释器解释或不能被编译器编译. 2.逻辑错误:由于不完整或不合法的输入所致,也可能是逻辑无法生存.计算或者输出结果需要的过程无法执行等. Python异常是一个对象,表示错误或意外情况 在python检测到一个错误时,将触发一个异常 1.python可以通过异常传导机制传递一个异常对象,发出一个异常情况出现的信号 2. 程序员也可以在代码中手动触发异常 python异常也可以理解为:程序出现了错误而在正常控制流以外采取

Python学习之异常重试解决方法详解

本文和大家分享的是在使用python 进行数据抓取中,异常重试相关解决办法,一起来看看吧,希望对大家学习python有所帮助. 在做数据抓取的时候,经常遇到由于网络问题导致的程序保存,先前只是记录了错误内容,并对错误内容进行后期处理. 原先的流程: defcrawl_page(url): pass deflog_error(url): pass url = "" try: crawl_page(url) except: log_error(url) 改进后的流程: attempts =

python学习之异常

上一次说了python类和对象的对象的创建方法,今天再来说一下python中异常的使用.在编写程序的使用,程序员需要辨别事件的正常过程和异常过程.这类事件的处理可以使用条件判断语句来进行,但是这么做不仅会影响程序的执行效率和不灵活,同时也会使程序更难以阅读.另外程序员不可能将所有程序可能出现的情况都考虑完全,所以使用异常机制有其重要性也有其必要性. 正如java c++语言的try/catch在python中也有其对应的语句,try/except.具体用法如下: #!/usr/bin/env p

Python学习9——异常

Python使用异常对象来表示异常状态,并在遇到错误时引发异常. raise语句可以引发异常,将一个类或实例作为参数. >>> raise Exception #引发的是通用异常,没有指出是什么错误 Traceback (most recent call last): File "<pyshell#120>", line 1, in <module> raise Exception Exception >>> >>

python学习_26(异常)

异常: try: <语句>#可能发生异常的代码 except<名字>: <语句>#如果在try部份引发了'name'异常 except<名字> as <异常参数>: <语句>#如果引发了'name'异常,获得附加的异常对象 else: <语句>#如果没有异常发生 finally: <语句>#始终都会执行的语句 嵌套异常捕获 try: try: 1/0 except IOError: print("IO

Python学习记录-异常捕获

记录错误 如果不捕获错误,自然可以让Python解释器来打印出错误堆栈,但程序也被结束了.既然我们能捕获错误,就可以把错误堆栈打印出来,然后分析错误原因,同时,让程序继续执行下去. Python内置的logging模块可以非常容易地记录错误信息: # err_logging.py import logging def foo(s): return 10 / int(s) def bar(s): return foo(s) * 2 def main(): try: bar('0') except

【python学习】8.异常

[python学习]8.异常 raise Exception: 抛出指定异常 try/except: 捕捉异常 except: 第一个参数是需要捕获的异常类型,可以是多个类型组成元组,第二个参数是捕获到的异常对象, raise: 抛出已经捕获的异常 else: 当没有捕获的异常时候执行 finally: 总会被执行 def test(): try: raise Exception("test") except (Exception), e: print "Exception&

python学习------------异常以及反射

学完这一节,python基础部分就要告一段落了,期待进入新一阶段的学习,也给自己说坚持就是胜利. 一.isinstance(obj,cls) 检查obj是否是cls的对象 1.首先从学过的变量开始 a = 12 b = "bb" print isinstance(a,int) #结果是True print isinstance(a,str) #结果是False print isinstance(b,str) #结果是True print isinstance(b,int) #结果是Fa