关于python:图解python-错误与异常处理

7次阅读

共计 5828 个字符,预计需要花费 15 分钟才能阅读完成。

作者:韩信子 @ShowMeAI
教程地址:http://www.showmeai.tech/tuto…
本文地址:http://www.showmeai.tech/article-detail/87
申明:版权所有,转载请分割平台与作者并注明出处


1.Python3 谬误和异样

咱们在理论编程过程中,常常会看到一些报错信息,在 python 中也有专门的形式去处理错误和异样,保障全局流程顺畅。

Python 中的语法错误和异样很容易被识别,咱们也能够借助 try…except 来做相应的解决。

2. 语法错误

初学者常常会遇到 Python 的语法错误或解析错,如下实代码示例

>>> while True print('Hello ShowMeAI')
  File "<stdin>", line 1, in ?
    while True print('Hello ShowMeAI')
                   ^
SyntaxError: invalid syntax

这个例子中,函数 print() 被查看到有谬误,在它后面短少了一个冒号 :

语法分析器指出了出错的一行,并且在最先找到的谬误的地位标记了一个小小的箭头。

3. 异样

即使 Python 程序的语法是正确的,在运行它的时候,也有可能产生谬误。运行期检测到的谬误被称为异样。

大多数的异样都不会被程序处理,都以错误信息的模式展示在这里(下列代码能够在在线 python3 环境中运行):

for i in range(5,-5,-1):
    print(5/i)

后果如下:

1.0
1.25
1.6666666666666667
2.5
5.0
Traceback (most recent call last):
  File "<string>", line 4, in <module>
ZeroDivisionError: division by zero

异样以不同的类型呈现,这些类型都作为信息的一部分打印进去: 例子中的类型有 ZeroDivisionError,NameError 和 TypeError。

错误信息的后面局部显示了异样产生的上下文,并以调用栈的模式显示具体信息。

4. 异样解决

(1)try-except

异样捕获能够应用 try/except 语句。

以下例子中,让用户输出一个非法的整数,然而容许用户中断这个程序(应用 Control-C 或者操作系统提供的办法)。用户中断的信息会引发一个 KeyboardInterrupt 异样。

while True:
    try:
        x = int(input("请输出一个数字:"))
        break
    except ValueError:
        print("您输出的不是数字,请再次尝试输出!")

try 语句依照如下形式工作;

  • 首先,执行 try 子句(在关键字 try 和关键字 except 之间的语句)。
  • 如果没有异样产生,疏忽 except 子句,try 子句执行后完结。
  • 如果在执行 try 子句的过程中产生了异样,那么 try 子句余下的局部将被疏忽。如果异样的类型和 except 之后的名称相符,那么对应的 except 子句将被执行。
  • 如果一个异样没有与任何的 except 匹配,那么这个异样将会传递给下层的 try 中。

一个 try 语句可能蕴含多个 except 子句,别离来解决不同的特定的异样,其中只有一个分支会被执行。

处理程序将只针对对应的 try 子句中的异样进行解决,而不是其余的 try 的处理程序中的异样。

一个 except 子句能够同时解决多个异样,这些异样将被放在一个括号里成为一个元组,例如:

except (RuntimeError, TypeError, NameError):
    pass

最初一个 except 子句能够疏忽异样的名称,它将被当作通配符应用。你能够应用这种办法打印一个错误信息,而后再次把异样抛出。

import sys

try:
    f = open('ShowMeAI.txt')
    s = f.readline()
    i = int(s.strip())
except OSError as err:
    print("零碎谬误: {0}".format(err))
except ValueError:
    print("无奈转换为整型")
except:
    print("未知谬误:", sys.exc_info()[0])
    raise

(2)try-except-else

try/except 语句还有一个可选的 else 子句,如果应用这个子句,那么必须放在所有的 except 子句之后。

else 子句将在 try 子句没有产生任何异样的时候执行。

以下实例在 try 语句中判断文件是否能够关上,如果关上文件时失常的没有产生异样则执行 else 局部的语句,读取文件内容:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print('无奈关上文件', arg)
    else:
        print(arg, '有', len(f.readlines()), '行')
        f.close()

应用 else 子句比把所有的语句都放在 try 子句外面要好,这样能够防止一些意想不到,而 except 又无奈捕捉的异样。

异样解决并不仅仅解决那些间接产生在 try 子句中的异样,而且还能解决子句中调用的函数(甚至间接调用的函数)里抛出的异样。例如:

>>> def this_fails():
        x = 1/0
   
>>> try:
        this_fails()
    except ZeroDivisionError as err:
        print('呈现谬误:', err)

#呈现谬误: int division or modulo by zero

(3)try-finally 语句

try-finally 语句无论是否产生异样都将执行最初的代码。

以下实例中 finally 语句无论异样是否产生都会执行:

try:
    runoob()
except AssertionError as error:
    print(error)
else:
    try:
        with open('ShowMeAI.log') as file:
            read_data = file.read()
    except FileNotFoundError as fnf_error:
        print(fnf_error)
finally:
    print('无论异样是否产生,都会执行本句话。')

5. 抛出异样

Python 应用 raise 语句抛出一个指定的异样。

raise 语法格局如下:

raise [Exception [, args [, traceback]]]

以下示例代码如果 x 大于 10 就触发异样:

x = 20
if x > 10:
    raise Exception('x 不能大于 10。x 的值为: {}'.format(x))

执行以上代码会触发异样:

Traceback (most recent call last):
  File "test.py", line 3, in <module>
    raise Exception('x 不能大于 5。x 的值为: {}'.format(x))
Exception: x 不能大于 10。x 的值为: 20

raise 惟一的一个参数指定了要被抛出的异样。它必须是一个异样的实例或者是异样的类(也就是 Exception 的子类)。

如果你只想晓得这是否抛出了一个异样,并不想去解决它,那么一个简略的 raise 语句就能够再次把它抛出。

>>> try:
        raise NameError('NewError')
    except NameError:
        print('An exception!')
        raise
   
An exception!
Traceback (most recent call last):
  File "<stdin>", line 2, in ?
NameError: NewError

6. 用户自定义异样

你能够通过创立一个新的异样类来领有本人的异样。异样类继承自 Exception 类,能够间接继承,或者间接继承,例如:

>>> class NewError(Exception):
        def __init__(self, value):
            self.value = value
        def __str__(self):
            return repr(self.value)
   
>>> try:
        raise NewError(2*2)
    except NewError as e:
        print('New exception occurred, value:', e.value)
   
My exception occurred, value: 4
>>> raise NewError('oops!')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
__main__.NewError: 'oops!'

在这个例子中,类 Exception 默认的 __init__() 被笼罩。

当创立一个模块有可能抛出多种不同的异样时,一种通常的做法是为这个包建设一个根底异样类,而后基于这个根底类为不同的谬误状况创立不同的子类:

class Error(Exception):
    """Base class for exceptions in this module."""
    pass

class InputError(Error):
    """Exception raised for errors 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 a state transition that's not
    allowed.

    Attributes:
        previous -- state at beginning of transition
        next -- attempted new state
        message -- explanation of why the specific transition is not allowed
    """

    def __init__(self, previous, next, message):
        self.previous = previous
        self.next = next
        self.message = message

大多数的异样的名字都以 ”Error” 结尾,就跟规范的异样命名一样。

7. 定义清理行为

try 语句还有另外一个可选的子句,它定义了无论在任何状况下都会执行的清理行为。例如:

>>> try:
...     raise KeyboardInterrupt
... finally:
...     print('Goodbye, ShowMeAI!')
...
Goodbye, ShowMeAI!
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt

以上例子不论 try 子句外面有没有产生异样,finally 子句都会执行。

如果一个异样在 try 子句里(或者在 except 和 else 子句里)被抛出,而又没有任何的 except 把它截住,那么这个异样会在 finally 子句执行后被抛出。

上面是一个更加简单的例子(在同一个 try 语句里蕴含 except 和 finally 子句):

>>> def divide(x, y):
        try:
            result = x / y
        except ZeroDivisionError:
            print("除数为 0!")
        else:
            print("后果为", result)
        finally:
            print("除法计算完结")
   
>>> divide(2, 1)
后果为 2.0
除法计算完结
>>> divide(2, 0)
除数为 0!
除法计算完结
>>> divide("2", "1")
除法计算完结
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'

8. 预约义的清理行为

一些对象定义了规范的清理行为,无论零碎是否胜利的应用了它,一旦不须要它了,那么这个规范的清理行为就会执行。

这面这个例子展现了尝试关上一个文件,而后把内容打印到屏幕上:

for line in open("ShowMeAI.txt"):
    print(line, end="")

以上这段代码的问题是,当执行结束后,文件会放弃关上状态,并没有被敞开。

关键词 with 语句就能够保障诸如文件之类的对象在应用完之后肯定会正确的执行他的清理办法:

with open("ShowMeAI.txt") as f:
    for line in f:
        print(line, end="")

以上这段代码执行结束后,就算在处理过程中出问题了,文件 f 总是会敞开。

9. 视频教程

请点击到 B 站查看【双语字幕】版本

https://www.bilibili.com/vide…

材料与代码下载

本教程系列的代码能够在 ShowMeAI 对应的 github 中下载,可本地 python 环境运行,能迷信上网的宝宝也能够间接借助 google colab 一键运行与交互操作学习哦!

本教程系列波及的 Python 速查表能够在以下地址下载获取:

  • Python 速查表

拓展参考资料

  • Python 教程—Python3 文档
  • Python 教程 - 廖雪峰的官方网站

ShowMeAI 相干文章举荐

  • python 介绍
  • python 装置与环境配置
  • python 根底语法
  • python 根底数据类型
  • python 运算符
  • python 条件管制与 if 语句
  • python 循环语句
  • python while 循环
  • python for 循环
  • python break 语句
  • python continue 语句
  • python pass 语句
  • python 字符串及操作
  • python 列表
  • python 元组
  • python 字典
  • python 汇合
  • python 函数
  • python 迭代器与生成器
  • python 数据结构
  • python 模块
  • python 文件读写
  • python 文件与目录操作
  • python 谬误与异样解决
  • python 面向对象编程
  • python 命名空间与作用域
  • python 工夫和日期

ShowMeAI 系列教程举荐

  • 图解 Python 编程:从入门到精通系列教程
  • 图解数据分析:从入门到精通系列教程
  • 图解 AI 数学根底:从入门到精通系列教程
  • 图解大数据技术:从入门到精通系列教程

正文完
 0