暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Python异常

糟老头修炼记 2020-02-15
467

1.python异常和错误的区别


(1). 错误


从软件方面来说,错误是语法或是逻辑上的。

语法错误指示软件的结构上有错误,导致不能被解释器解释或编译器无法编译。这些错误必须在程序执行前纠正。当程序的语法正确后,剩下的就是逻辑错误了。逻辑错误可能是由于不完整或是不合法的输入所致;在其他情况下,还可能是逻辑无法生成,计算,或是输出结果需要的过程无法执行。这些错误通常分别被称为域错误和范围错误。


当 Python 检测到一个错误时,解释器就会指出当前流已经无法继续执行下去,这时候就出现了异常。


(2). 异常


对异常的最好描述是: 它是因为程序运行时出现了错误(程序运行时出现的错误有:除0、下标越界、文件不存在、网络异常、类型错误、名字错误等

)而在正常控制流以外采取的行为。这个行为又分为两个阶段: 首先是引起异常发生的错误,然后是检测(和采取可能的措施)阶段。


第一个阶段是在发生了一个异常条件(有时候也叫做例外的条件)后发生的。

只要检测到错误并且意识到异常条件,解释器会引发一个异常。


Python 也允许程序员自己通过raise语句显式的引发异常,无论是 Python 解释器还是程序员引发的,异常就是错误发生的信号,当前流将被打断,用来处理这个错误并采取相应的操作,这就是第二阶段。


对异常的处理发生在第二阶段。异常引发后,可以调用很多不同的操作,可以是忽略错误(记录错误但不采取任何措施, 采取补救措施后终止程序)

,或是减轻问题的影响后设法继续执行程序。所有的这些操作都代表一种继续,或是控制的分支,关键是程序员在错误发生时可以指示程序如何执行。


由于有了运行时管理错误的能力,应用程序的健壮性有了很大的提高。


在编程时应避免过多依赖异常处理机制来提高程序健壮性


常见异常类的继承层次:


在Python内可以继承Python内置异常类来实现自定义的异常类。如果编写的某个模块需要抛出多个不同但相关的异常,可以先创建一个基类,然后创建多个派生类分别表示不同的异常


    class Error(Exception):
    pass


    class InputError(Error):
    """exception raised for error in the input
    Attributes:
    expression--input expression in which the error occurred message--explanation of the error"""

    def __init__(self,expression,message):
    self.expression=expression
    self.message=message


    class TransitionError(Error):
    """raised when an operation attempts s state..."""
    def __init__(self,previous,next,message):
    self.previous=previous
    self.next=next
    self.message=message



    Python 采用了 “try...except” 块和 “catching/捕获” 块的概念,而且它在异常处理方面更有”纪律性”。


    2.try...except结构:try子句中的代码块包含可能出现的错误,而except子句用来捕捉相应的异常,except子句中的代码用来处理异常

    如果try中的代码没有出现异常,则继续往下执行异常结构后面的代码;

    如果出现异常,则被except捕捉,则执行except子句中的异常处理代码;

    如果出现异常但没有被except捕捉,则继续往外层抛;

    如果所有层走没有捕捉并处理该异常,则程序终止并将该异常抛给最终用户

      try:
      try
      except Exception[as reason]:
      except

      如果需要捕获所有类型的异常,可以使用BaseException,即Python异常类的基类(不建议):

        try:
        ...
        except BaseException as e:
        except

        对于异常结构,一般是尽量显式捕捉可能会出现的异常,并且有针对性的处理。但是为了避免遗漏没有得到处理的异常干扰程序的执行,在捕捉了所有可能出现的异常后

        ,可以使用异常处理结构的最后一个except来捕捉BaseException

          while True:
          try:
          x=int('please enter a number:')
          break
          except ValueError:
          pritn('that was not a vaild number,try again...')

          在使用时,except子句可以在异常类名字后面指定一个变量,用来捕获异常的参数或更详细的信息


            try:
            raise Exception('spam','eggs')
            except Exception as inst:
            print(type(inst))
            print(inst.args)
            print(inst)




            x,y=inst.args
            print('x=',x)
            print('y=',y)

            3.try...except...else结构:

            如果try中的代码抛出的异常被except捕捉,则执行相应的异常处理代码,这种情况下不执行else中的代码;如果try中的代码没有抛出任何异常,则执行else中的代码


              a_list=['app','bpp','cpp']
              while True:
              n=input('please enter a number:')
              try:
              n=int(n)
              pritn(a_list)
              except IndexError:
              pritn('error,try again,,,')
              else:
              break

              带有多个except的try结构:

                try:
                try
                except Exception1:
                except1




                except Exception2:
                except2




                except Exception3:
                except3
                  try:
                  x=input('输入被除数:')
                  y=input('输入除数:')
                  z=float(x)/float(y)




                  except ZeroDivisionError:
                  print('不能除0')
                  except TypeError:
                  print('类型。。。')
                  except NameError:
                  print('变量不存在')
                  else:
                  print(x,'/',y,'=',z)


                  将要捕获的异常写在一个元组里,可以使用一个except语句捕获多个异常,并且共用同一段异常处理代码

                    import sys
                    try:
                    f=open('data.txt')
                    s=f.readline()
                    i=int(s.strip())
                    except (OSError,ValueError,RuntimeError,NameError):
                    pass #占位符


                    4.try...except...finally结构:

                    finally子句中的语句块无论是否会发生异常都会执行,常用来做一些清理工作以释放try子句中申请的资源

                      >>> try:
                      3/0
                      except:
                      print(3)
                      finally:
                        print(5)

                      3
                      5
                        try:
                        f=open('data.txt')
                        line=f.readline()
                        print(line)
                        finally:
                        f.close() #无论读取文件是否发生异常,都能保证正常关闭该文件


                        但是,如果try子句中的异常没有被捕捉和处理,或者except子句或else子句的代码出现了异常,那么这些异常将会在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: unsupported operand type(s) for : 'str' and 'str'


                          finally中的代码可能会抛出异常,使用异常处理结构的本意是防止文件读取操作出现异常而导致文件不能正常关闭,但是如果因为文件不存在而导致文件对象创建失败,那么finally子句中关闭文件对象的代码将会抛出异常从而导致程序终止

                            >>> try:
                            f=open('data.txt','r')
                            line=f.readline()
                            print(line)
                            finally:
                            f.close()


                            NameError: name 'f' is not defined



                            5断.言与上下文处理:两种特殊的异常处理方式,在形式上比异常处理结构简单,能够满足简单的异常处理或条件确认,而且可以与标准的异常处理结构相结合


                            断言语句语法:

                              assert expression[,reason]

                              当判断表达式expression为真时,什么都不做,如果表达式为假,则抛出异常

                              assert语句一般用于对程序某个时刻必须满足的条件进行验证,仅当‘__debug__’为True时有效


                              断言与标准的异常处理结构结合使用:

                                >>> try:


                                assert 1==2,'1 is not equal 2'
                                except AssertionError as reason:
                                print('%s:%s'%(reason.__class__.__name__,reason))
                                AssertionError:'1 is not equal 2'




                                AssertionError:1 is not equal 2

                                上下文管理:使用上下文管理with语句可以自动管理资源,在代码块执行完毕后自动还原进入该代码块之前的现场或上下文。不论何种原因跳出with块,也不论是否发生异常,总能保证资源被正确释放,大大简化了程序员的工作,常用于文件操作、网络通信之类的场合

                                  with语法:
                                  with context_expr [as var]:
                                  with
                                    with open('data.txt') as f:
                                    for line in f:
                                    print(line)


                                    用sys模块回溯最后的异常:

                                    语法:

                                      import sys


                                      try:
                                      block
                                      except:
                                      t=sys.exc_info()
                                      print(t)
                                        >>1/0
                                        ZeroDivisionError: division by zero


                                        >>> import sys
                                        >>> try:
                                        1/0
                                        except:
                                        t=sys.exc_info()
                                        print(t)
                                        (<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero'), <traceback object at 0x01E722B0>)




                                        >>> def A():
                                        1/0


                                        >>> def B():
                                        A()
                                         
                                        >>> def C():
                                        B()


                                        >>> C()
                                        Traceback (most recent call last):
                                        File "<pyshell#58>", line 1, in <module>
                                        C()
                                        File "<pyshell#57>", line 2, in C
                                        B()
                                        File "<pyshell#54>", line 2, in B
                                        A()
                                        File "<pyshell#51>", line 2, in A
                                        1/0
                                        ZeroDivisionError: division by zero
                                        >>> try:
                                        C()
                                        except:
                                        t=sys.exc_info()
                                          print(t)

                                        (<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero'), <traceback object at 0x01E72210>)


                                        使用IDLE调试代码:

                                        IDLE Debig--Debugger菜单打开调试器窗口,然后打开要运行的程序,最后切换至调试器窗口使用其中的控制按钮进行调试,可以实时查看变量的当前值并跟踪其变化过程


                                        文章转载自糟老头修炼记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                        评论