zoukankan      html  css  js  c++  java
  • python异常处理

    try & except 块

    写代码的时候,出现错误必不可免,即使代码没有问题,也可能遇到别的问题。

    看下面这段代码:

    import math
    
    while True:
        text = raw_input('> ')
        if text[0] == 'q':
            break
        x = float(text)
        y = math.log10(x)
        print "log10({0}) = {1}".format(x, y)
    

    这段代码接收命令行的输入,当输入为数字时,计算它的对数并输出,直到输入值为 q 为止。

    乍看没什么问题,然而当我们输入0或者负数时:

    import math
    
    while True:
        text = raw_input('> ')
        if text[0] == 'q':
            break
        x = float(text)
        y = math.log10(x)
        print "log10({0}) = {1}".format(x, y)
    
    > -1
    
    
    
    ---------------------------------------------------------------------------
    
    ValueError                                Traceback (most recent call last)
    
    <ipython-input-1-ceb8cf66641b> in <module>()
          6         break
          7     x = float(text)
    ----> 8     y = math.log10(x)
          9     print "log10({0}) = {1}".format(x, y)
    
    
    ValueError: math domain error
    

    log10 函数会报错,因为不能接受非正值。

    一旦报错,程序就会停止执行,如果不希望程序停止执行,那么我们可以添加一对 try & except

    import math
    
    while True:
        try:
            text = raw_input('> ')
            if text[0] == 'q':
                break
            x = float(text)
            y = math.log10(x)
            print "log10({0}) = {1}".format(x, y)
        except ValueError:
            print "the value must be greater than 0"
    

    一旦 try 块中的内容出现了异常,那么 try 块后面的内容会被忽略,Python会寻找 except 里面有没有对应的内容,如果找到,就执行对应的块,没有则抛出这个异常。

    在上面的例子中,try 抛出的是 ValueErrorexcept 中有对应的内容,所以这个异常被 except 捕捉到,程序可以继续执行:

    import math
    
    while True:
        try:
            text = raw_input('> ')
            if text[0] == 'q':
                break
            x = float(text)
            y = math.log10(x)
            print "log10({0}) = {1}".format(x, y)
        except ValueError:
            print "the value must be greater than 0"
    
    > -1
    the value must be greater than 0
    > 0
    the value must be greater than 0
    > 1
    log10(1.0) = 0.0
    > q
    

    本人对于Python学习创建了一个小小的学习圈子,为各位提供了一个平台,大家一起来讨学习Python。欢迎各位到来Python学习群:960410445一起讨论视频分享学习。Python是未来的展方向,正在挑战我们的分析能力及对世界的认知方式,因此,我们与时俱进,迎接变化,并不断成长,掌握Python核心技术,才是掌握真正的价值所在。

    捕捉不同的错误类型

    import math
    
    while True:
        try:
            text = raw_input('> ')
            if text[0] == 'q':
                break
            x = float(text)
            y = 1 / math.log10(x)
            print "log10({0}) = {1}".format(x, y)
        except ValueError:
            print "the value must be greater than 0"
    

    假设我们将这里的 y 更改为 1 / math.log10(x),此时输入 1

    import math
    
    while True:
        try:
            text = raw_input('> ')
            if text[0] == 'q':
                break
            x = float(text)
            y = 1 / math.log10(x)
            print "log10({0}) = {1}".format(x, y)
        except ValueError:
            print "the value must be greater than 0"
    
    > 1
    
    
    
    ---------------------------------------------------------------------------
    
    ZeroDivisionError                         Traceback (most recent call last)
    
    <ipython-input-3-7607f1ae6af9> in <module>()
          7             break
          8         x = float(text)
    ----> 9         y = 1 / math.log10(x)
         10         print "log10({0}) = {1}".format(x, y)
         11     except ValueError:
    
    
    ZeroDivisionError: float division by zero
    

    因为我们的 except 里面并没有 ZeroDivisionError,所以会抛出这个异常,我们可以通过两种方式解决这个问题:

    捕捉所有异常

    except 的值改成 Exception 类,来捕获所有的异常。

    import math
    
    while True:
        try:
            text = raw_input('> ')
            if text[0] == 'q':
                break
            x = float(text)
            y = 1 / math.log10(x)
            print "1 / log10({0}) = {1}".format(x, y)
        except Exception:
            print "invalid value"
    
    > 1
    invalid value
    > 0
    invalid value
    > -1
    invalid value
    > 2
    1 / log10(2.0) = 3.32192809489
    > q
    

    指定特定值

    这里,我们把 ZeroDivisionError 加入 except

    import math
    
    while True:
        try:
            text = raw_input('> ')
            if text[0] == 'q':
                break
            x = float(text)
            y = 1 / math.log10(x)
            print "1 / log10({0}) = {1}".format(x, y)
        except (ValueError, ZeroDivisionError):
            print "invalid value"
    
    > 1
    invalid value
    > -1
    invalid value
    > 0
    invalid value
    > q
    

    或者另加处理:

    import math
    
    while True:
        try:
            text = raw_input('> ')
            if text[0] == 'q':
                break
            x = float(text)
            y = 1 / math.log10(x)
            print "1 / log10({0}) = {1}".format(x, y)
        except ValueError:
            print "the value must be greater than 0"
        except ZeroDivisionError:
            print "the value must not be 1"
    
    > 1
    the value must not be 1
    > -1
    the value must be greater than 0
    > 0
    the value must be greater than 0
    > 2
    1 / log10(2.0) = 3.32192809489
    > q
    

    事实上,我们还可以将这两种方式结合起来,用 Exception 来捕捉其他的错误:

    import math
    
    while True:
        try:
            text = raw_input('> ')
            if text[0] == 'q':
                break
            x = float(text)
            y = 1 / math.log10(x)
            print "1 / log10({0}) = {1}".format(x, y)
        except ValueError:
            print "the value must be greater than 0"
        except ZeroDivisionError:
            print "the value must not be 1"
        except Exception:
            print "unexpected error"
    
    > 1
    the value must not be 1
    > -1
    the value must be greater than 0
    > 0
    the value must be greater than 0
    > q
    

    得到异常的具体信息

    在上面的例子中,当我们输入不能转换为浮点数的字符串时,它输出的是 the value must be greater than 0,这并没有反映出实际情况。

    float('a')
    
    ---------------------------------------------------------------------------
    
    ValueError                                Traceback (most recent call last)
    
    <ipython-input-8-99859da4e72c> in <module>()
    ----> 1 float('a')
    
    
    ValueError: could not convert string to float: a
    

    为了得到异常的具体信息,我们将这个 ValueError 具现化:

    import math
    
    while True:
        try:
            text = raw_input('> ')
            if text[0] == 'q':
                break
            x = float(text)
            y = 1 / math.log10(x)
            print "1 / log10({0}) = {1}".format(x, y)
        except ValueError as exc:
            if exc.message == "math domain error":
                print "the value must be greater than 0"
            else:
                print "could not convert '%s' to float" % text
        except ZeroDivisionError:
            print "the value must not be 1"
        except Exception as exc:
            print "unexpected error:", exc.message
    
    > 1
    the value must not be 1
    > -1
    the value must be greater than 0
    > aa
    could not convert 'aa' to float
    > q
    

    同时,我们也将捕获的其他异常的信息显示出来。

    这里,exc.message 显示的内容是异常对应的说明,例如

    ValueError: could not convert string to float: a
    

    对应的 message

    could not convert string to float: a
    

    当我们使用 except Exception 时,会捕获所有的 Exception 和它派生出来的子类,但不是所有的异常都是从 Exception 类派生出来的,可能会出现一些不能捕获的情况,因此,更加一般的做法是使用这样的形式:

    try:
        pass
    except:
        pass
    

    这样不指定异常的类型会捕获所有的异常,但是这样的形式并不推荐。

    自定义异常

    异常是标准库中的类,这意味着我们可以自定义异常类:

    class CommandError(ValueError):
        pass
    

    这里我们定义了一个继承自 ValueError 的异常类,异常类一般接收一个字符串作为输入,并把这个字符串当作异常信息,例如:

    valid_commands = {'start', 'stop', 'pause'}
    
    while True:
        command = raw_input('> ')
        if command.lower() not in valid_commands:
            raise CommandError('Invalid commmand: %s' % command)
    
    > bad command
    
    
    
    ---------------------------------------------------------------------------
    
    CommandError                              Traceback (most recent call last)
    
    <ipython-input-11-0e1f81a1136d> in <module>()
          4     command = raw_input('> ')
          5     if command.lower() not in valid_commands:
    ----> 6         raise CommandError('Invalid commmand: %s' % command)
    
    
    CommandError: Invalid commmand: bad command
    

    我们使用 raise 关键词来抛出异常。

    我们可以使用 try/except 块来捕捉这个异常:

    valid_commands = {'start', 'stop', 'pause'}
    
    while True:
        command = raw_input('> ')
        try:
            if command.lower() not in valid_commands:
                raise CommandError('Invalid commmand: %s' % command)
        except CommandError:
            print 'Bad command string: "%s"' % command
    

    由于 CommandError 继承自 ValueError,我们也可以使用 except ValueError 来捕获这个异常。

    finally

    try/catch 块还有一个可选的关键词 finally。

    不管 try 块有没有异常, finally 块的内容总是会被执行,而且会在抛出异常前执行,因此可以用来作为安全保证,比如确保打开的文件被关闭。。

    try:
        print 1
    finally:
        print 'finally was called.'
    
    1
    finally was called.
    

    在抛出异常前执行:

    try:
        print 1 / 0
    finally:
        print 'finally was called.'
    
    finally was called.
    
    
    
    ---------------------------------------------------------------------------
    
    ZeroDivisionError                         Traceback (most recent call last)
    
    <ipython-input-13-87ecdf8b9265> in <module>()
          1 try:
    ----> 2     print 1 / 0
          3 finally:
          4     print 'finally was called.'
    
    
    ZeroDivisionError: integer division or modulo by zero
    

    如果异常被捕获了,在最后执行:

    try:
        print 1 / 0
    except ZeroDivisionError:
        print 'divide by 0.'
    finally:
        print 'finally was called.'
    
    divide by 0.
    finally was called.
    

    警告

    出现了一些需要让用户知道的问题,但又不想停止程序,这时候我们可以使用警告:

    首先导入警告模块:

    import warnings
    

    在需要的地方,我们使用 warnings 中的 warn 函数:

    warn(msg, WarningType = UserWarning)
    
    def month_warning(m):
        if not 1<= m <= 12:
            msg = "month (%d) is not between 1 and 12" % m
            warnings.warn(msg, RuntimeWarning)
    
    month_warning(13)
    
    c:Anacondalibsite-packagesIPythonkernel\__main__.py:4: RuntimeWarning: month (13) is not between 1 and 12
    

    有时候我们想要忽略特定类型的警告,可以使用 warningsfilterwarnings 函数:

    filterwarnings(action, category)
    

    action 设置为 'ignore' 便可以忽略特定类型的警告:

    warnings.filterwarnings(action = 'ignore', category = RuntimeWarning)
    
    month_warning(13)
    
  • 相关阅读:
    0309. Best Time to Buy and Sell Stock with Cooldown (M)
    0621. Task Scheduler (M)
    0106. Construct Binary Tree from Inorder and Postorder Traversal (M)
    0258. Add Digits (E)
    0154. Find Minimum in Rotated Sorted Array II (H)
    0797. All Paths From Source to Target (M)
    0260. Single Number III (M)
    0072. Edit Distance (H)
    0103. Binary Tree Zigzag Level Order Traversal (M)
    0312. Burst Balloons (H)
  • 原文地址:https://www.cnblogs.com/paisenpython/p/10266550.html
Copyright © 2011-2022 走看看