错误和异常处理

Posted xdlzs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了错误和异常处理相关的知识,希望对你有一定的参考价值。

Python有两种错误很容易辨认:语法错误和异常。

1 什么是异常?

异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。
一般情况下,在Python无法正常处理程序时就会发生一个异常。
如:有些是由于拼写、配置、选项等等各种引起的程序错误,有些是由于程序功能处理逻辑不完善引起的漏洞,这些统称为程序中的异常

异常是Python对象,表示一个错误。
当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。

常见异常如:

  1. 语法错误:SyntaxError:invalid syntax


     
    技术分享图片
    2018-04-02_215304.png

2.变量名不存在:NameError:name ‘b‘ is not defined


 
技术分享图片
2018-04-02_215935.png

3.索引错误:IndexError: list index out of range


 
技术分享图片
2018-04-02_220226.png

4.关键字错误:KeyError: ‘c‘


 
技术分享图片
2018-04-02_220450.png

5.类型错误:TypeError: list indices must be integers, not str


 
技术分享图片
2018-04-02_220741.png

6.参数传值错误:ValueError: invalid literal for int() with base 10: ‘ab‘(主要发生在函数里面)


 
技术分享图片
2018-04-02_221813.png

7.属性错误:AttributeError: A instance has no attribute ‘acc‘


 
技术分享图片
2018-04-02_222234.png

8.输入输出错误:IOError


 
技术分享图片
2018-04-02_222542.png

解决方案◆

  • 如果是拼写、配置等等引起的错误,根据出错信息进行排查错误出现的位置进行解决
  • 如果是程序设计不完善引起的漏洞,根据漏洞的情况进行设计处理漏洞的逻辑;

2 错误处理

错误的出现,在程序中一般会有两种表现,一种是拼写错误,一种是程序执行过程中出现的错误,这样两种不同的错误应该怎么进行追踪和处理呢?

2.1. 拼写错误

常规情况下,拼写错误只是在简单的记事本等环境下进行开发时,容易手误产生拼写错误;当前开发环境下,我们经常使用一些半自动化的IDE开发工具,如pycharm等等,可以进行简单的程序关键字的拼写检查以及程序结构的检查,把一些简单的拼写问题掐死在萌芽之中

2.2程序运行时错误

程序运行过程中,也会出现各种各样的错误,对于错误的出现和提示信息必须有一个比较明确的掌握,才能在后续的程序开发中快速的开发并且修复问题,这里就会出现两个步骤

  • 确定问题及问题出现的代码行
  • 后续的问题处理【参考后面的异常处理】

3 异常处理方式

python程序中出现的异常信息,主要有两种处理操作方式
? 直接处理异常,保证程序正常执行
? 抛出异常,告知调用者出现的重要错误信息

捕捉异常可以使用try/except语句。
(1). 直接处理异常

 c = int(input("请输入整数选项:"))  print("用户输入了:%d" % c) 

 上述代码,正常执行过程中,如果用户输入了字母会出现ValueError异常错误信息
请输入整数选项:d
Traceback (most recent call last):
  File "D:/Py1801_B/DATE2/python高级/多线程/text.py", line 18, in <module>
    c = int(input("请输入整数选项:"))
ValueError: invalid literal for int() with base 10: ‘d‘

捕捉异常

# 捕捉异常 1
try:      
    c = int(input("请输入整数选项:"))                                       
    print("用户输入了:%d" % c)  # 处理异常
except:      
  print("出现了异常,用户输入了非法数据") 

通过try捕捉可能出现的异常,如果出现异常~并不让程序直接崩溃退出,而是执行except中的代码块来处理出现的异常

上述代码中,可以通过except处理在try代码块中出现的任意异常 

#捕捉异常2
try:      
  c = int(input("请输入整数选项:"))     
  print("用户输入了:%d" % c)  # 处理指定异常
except ValueError:     
   print("出现了异常,用户输入了非法数据")

可以在except关键字后面,添加指定的异常名称,来处理指定的异常;只有捕捉到该指定异常时except代码块才会执行

(2) .给异常信息定义别名

# 捕捉异常
try:
    c = int(input("请输入整数选项:"))
    print("用户输入了:%d" % c)
# 处理指定的异常并获取异常信息
except ValueError as e:
    print("出现了异常,用户输入了非法数据", e)

上述代码中,在except中指定了处理的异常信息,并且通过as别名的方式将异常信息保存在了一个变量e中,后续可以通过变量e打印出现的异常信息

(3). 精确、同时处理多个异常

try:
    # 可能会出现文件找不到的异常:FileNotFoundError
    file = open("d:/test.txt", "r")

    # 可能会出现类型异常:ValueError
    c = int(input("请输入整数选项:"))
    print("用户输入了:%d" % c)
# 指定需要处理的多个异常类型,包含在一个元组中
except (ValueError, FileNotFoundError) as e:
    print("出现了异常", e)

运行结果:
出现了异常 [Errno 2] No such file or directory: ‘d:/test.txt‘
如上述代码所示,将多个需要处理的异常信息,进行精确的异常捕捉来提高程序代码的容错性能

(4). 精确、分步处理多个异常

try:
    # 可能会出现文件找不到的异常:FileNotFoundError
    file = open("d:/test.txt", "r")

    # 可能会出现类型异常:ValueError
    c = int(input("请输入整数选项:"))
    print("用户输入了:%d" % c)
# 指定需要处理的多个异常类型,可以通过多个except叠加完成
except ValueError as e:
    print("出现了非法输入异常", e)
except FileNotFoundError as e:
    print("文件操作出现异常", e)
except Exception as e:
    print("程序中出现了异常", e)

通过多个except叠加,进行异常的精确捕捉和精确处理

(5). 异常处理关键字finally

try:
    f = open("d:/oCam.rar", "rb")
except FileNotFoundError as e:
    print("文件操作出现异常", e)
except Exception as e:
    print("程序中出现了异常", e)
finally:
    # finally模块中的代码,不论是否出现异常,最终都会执行的代码块
    # 关闭文件,释放资源
    f.close()

finally关键字比较特殊,主要是针对异常处理过程中的两种分支进行一个统一的处理
代码中根据是否出现异常会出现两个分支
分支一:代码中没有异常,try中的代码正常执行结束
分支二:代码中出现异常,从异常代码开始执行except中的代码
但是不论执行那个分支,最后进行统一的资源回收时必须执行相同的代码,所以finally关键字就出现了

(6). 异常处理关键字else

‘‘‘
try:
    # 可能出现异常的代码
except ValueError as e:
    # 处理异常的代码
except FileNotFoundError as e:
    # 处理异常的代码
except:
    # 异常的通用处理
[else:]
    [# try中没有异常,才会执行的代码]
[finally:]
    [# 无论try中是否出现异常,都会执行的代码]
‘‘‘
try:
    f = open("d:/test.txt", "rb")
except FileNotFoundError as e:
    print("文件操作出现异常", e)
except Exception as e:
    print("程序中出现了异常", e)
else:
    print("try中没有出现异常")
finally:
    # finally模块中的代码,不论是否出现异常,最终都会执行的代码块
    # 关闭文件,释放资源
    f.close()

else关键字是一种语法糖,主要是将try中的代码进行了分离处理,将可能出现异常的代码和之后的代码分别安排在了不同的代码块中,主要目的是提高程序代码的可读性;但是实际项目操作过程中使用并不是很多,尤其是在try中或者except中出现了if语句的时候,else关键字使用反倒并不是尽如人意了。
(7). 抛出异常

# raise ValueError("出现错误")

try:
    c = int(input("请输入选项:"))
    print("用户输入了选项:%d" % c)
except ValueError as e:
    # 转换成一个比较清楚的异常
    # 但是问题是:直接使用系统的异常名称,不是特别友好!
    raise ValueError("类型转换错误")

抛出异常:是异常处理中经常用到的手段,主要是给函数的调用者抛出异常信息,要求调用的开发人员
对传递的数据有一个比较强制的约束

抛出异常:比较常用的手段就是抛出自定义异常
因为系统的某些内建异常,解读起来还是比较有代沟的!在这样的情况下,将比较复杂的系统异常
转换成自定义的信息比较准确的异常数据展示,会更加友好!

4 自定义异常

自定义异常,是根据程序中功能的需要,定义的和项目本身结合比较紧密的个性化的异常信息;自定义异常应用比较广泛,主要分两个步骤进行操作

  • 定义自定义异常
  • 在合适的位置抛出异常

通常情况下,python中的自定义异常,都会选择从系统标准异常Exception进行继承实现,如下:

class MyException(Exception):
def __init__(self, message):
            self.message = message

def __str__(self):
            return “异常描述:%s” % self.message

抛出异常的操作比较简单,通过关键字raise直接抛出异常即可

raise MyException(“出现了自定义异常”)

结合案例:

class MyException(Exception):
    ‘‘‘
    自定义异常
    ‘‘‘
    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        return "异常描述:%s" % self.msg

# 捕捉异常
try:
    # 用户输入数据
    num1 = float(input("请输入第一个数据:"))
    num2 = float(input("请输入第二个数据:"))
    res = num1 / num2
# 处理类型异常
except ValueError:
    print("只能输入数字")
    raise MyException("只能输入数字,但是用户输入了其他非数字字符")
# 处理0除数异常
except ZeroDivisionError:
    print("0不能做为除数")
    raise MyException("亲,不能用0做为除数的")
# 正常结果
else:
    # 打印展示结果
    print("除法运算结果:%.2f" % res)
finally:
    print("计算过程结束")

运行结果:

请输入第一个数据:q
Traceback (most recent call last):
只能输入数字
计算过程结束
  File "D:/Py1801_B/DATE2/python高级/多线程/text.py", line 30, in <module>
    num1 = float(input("请输入第一个数据:"))
ValueError: could not convert string to float: ‘q‘

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:/Py1801_B/DATE2/python高级/多线程/text.py", line 36, in <module>
    raise MyException("只能输入数字,但是用户输入了其他非数字字符")
__main__.MyException: 异常描述:只能输入数字,但是用户输入了其他非数字字符

5 python标准异常

异常名称描述
BaseException 所有异常的基类
SystemExit 解释器请求退出
KeyboardInterrupt 用户中断执行(通常是输入^C)
Exception 常规错误的基类
StopIteration 迭代器没有更多的值
GeneratorExit 生成器(generator)发生异常来通知退出
StandardError 所有的内建标准异常的基类
ArithmeticError 所有数值计算错误的基类
FloatingPointError 浮点计算错误
OverflowError 数值运算超出最大限制
ZeroDivisionError 除(或取模)零 (所有数据类型)
AssertionError 断言语句失败
AttributeError 对象没有这个属性
EOFError 没有内建输入,到达EOF 标记
EnvironmentError 操作系统错误的基类
IOError 输入/输出操作失败
OSError 操作系统错误
WindowsError 系统调用失败
ImportError 导入模块/对象失败
LookupError 无效数据查询的基类
IndexError 序列中没有此索引(index)
KeyError 映射中没有这个键
MemoryError 内存溢出错误(对于Python 解释器不是致命的)
NameError 未声明/初始化对象 (没有属性)
UnboundLocalError 访问未初始化的本地变量
ReferenceError 弱引用(Weak reference)试图访问已经垃圾回收了的对象
RuntimeError 一般的运行时错误
NotImplementedError 尚未实现的方法
SyntaxError Python 语法错误
IndentationError 缩进错误
TabError Tab 和空格混用
SystemError 一般的解释器系统错误
TypeError 对类型无效的操作
ValueError 传入无效的参数
UnicodeError Unicode 相关的错误
UnicodeDecodeError Unicode 解码时的错误
UnicodeEncodeError Unicode 编码时错误
UnicodeTranslateError Unicode 转换时错误
Warning 警告的基类
DeprecationWarning 关于被弃用的特征的警告
FutureWarning 关于构造将来语义会有改变的警告
OverflowWarning 旧的关于自动提升为长整型(long)的警告
PendingDeprecationWarning 关于特性将会被废弃的警告
RuntimeWarning 可疑的运行时行为(runtime behavior)的警告
SyntaxWarning 可疑的语法的警告
UserWarning 用户代码生成的警告

以上是关于错误和异常处理的主要内容,如果未能解决你的问题,请参考以下文章

片段中的Android致命异常

使用实体框架迁移时 SQL Server 连接抛出异常 - 添加代码片段

PCL异常处理:pcl 1.8.13rdpartyoostincludeoost-1_64oost ypeofmsvc ypeof_impl.hpp(125): error(代码片段

片段中的 Listview 适配器给出空指针异常

使用片段中的处理程序时出现非法状态异常

片段中的 EditText 上的空指针异常 [重复]