MyPython-->进阶篇-->异常

Python使用被称为对象的特殊对象来管理程序执行期间发生的错误。每当发生让pthon不知所措的错误时,他都会创建一个异常对象。如果你编写了处理该异常的代码,程序将继续运行,否则程序将停止并显示一个traceback,其中包含有关异常的报告。

异常是使用try-except代码块来处理的。代码块让python执行指定的操作,同时告诉python发生异常时怎么办。

处理ZeroDivisionError异常

将一个数字除以零

print(1/0)
#报以下错误
Traceback (most recent call last):
  File "D:/pythontest/pycharmt/day9/pitest.py", line 41, in <module>
    print(1/0)
ZeroDivisionError: division by zero

这种情况下python停止运行并告诉你引发了哪种异常,ZerDivisionError错误是一个异常对象。我们可以增加代码防止这种情况

try:
    print(1/0)
except ZeroDivisionError:
    print('no  zero')

使用try-except代码块来处理可能触发的异常。将可能出错的代码放到try内,在except中放入出错后希望运行的代码。如果没有出错,就跳过except代码中的内容

else 代码块

通过将可能会引发错误的代码放到代码块tr-except中,可提高这个程序抵御错误的能力。有赖于try代码成功执行的代码都应该放到else里 

while 1:
    num_1 = input('enter first num ')
    num_2 = input('enter second num')
    try:
        print(int(num_1)/int(num_2))
    except ZeroDivisionError:
        print('no zero ')
    else:
        answer = int(num_1)/int(num_2)

将可能引发错误的代码放入try中,将对触发错误代码后执行的放到except中,将try代码执行成功后要执行的放在else代码块中

通过预测可能发生错误的代码,可编写健壮的程序,他们即便面临无效数据或缺少资源,也能继续运行,从而能抵御无意的用户错误和恶意的攻击

处理FileNotFoundError异常

来读取一个不存在的文件

with open('cc.txt') as file_object:
    file_txt = file_object.read()
Traceback (most recent call last):
  File "D:/python/pycharmtest/day12/filetest.py", line 15, in <module>
    with open('cc.txt') as file_object:
FileNotFoundError: [Errno 2] No such file or directory: 'cc.txt

python找不到要打开的文件,于是创建了FileNotFoundError对相关,这个错误时open产生的

ry:
    with open('cc.txt') as file_object:
        file_txt = file_object.read()
except FileNotFoundError:
    print('file not found')

分析文本

with open('blog.txt')as file_object:
#     cont = ''
#     try:
#         contents = file_object.read()
#         for x in contents:
#             x = ''.join(x.split(' '))
#             cont += x.strip()
#     except UnicodeDecodeError:
#         print('编码错误')
# print(cont)
# print(len(cont))

使用多个文件

def file_count(file_name):
    try:
        with open(file_name) as file_object:
            contents = file_object.read()
    except FileNotFoundError:
        print('%s is not found'%file_name)
    else:
        content = ''.join(contents.split())
        print('%s count %s'%(file_name,len(content)))
file_name = ['blog.txt','pi.txt','cc.txt']
for x in file_name:
    file_count(x)


输出

blog.txt count 20
pi.txt count 1197
cc.txt is not found

失败时一声不吭

try:
    with open('no.txt') as file_object:
        contents = file_object.read()
except FileNotFoundError:
    pass
else:
    print(len(contents.split()))

在找不到文件时pass什么都不做,pass也充当一个占位符的作用

ValueError

while 1:
    num_1 = input('enter frist num')
    num_2 = input('enter second num')
    try:
        answer = int(num_1)/int(num_2)
    except ValueError:
        print('no chr')
    else:
        answer = int(num_1)/int(num_2)
        print(answer)

 记录错误

如果不捕获错误,自然还可以让python解释器来打印处错误堆栈,但程序也被结束了。既然我们能捕获错误,就可以把错误堆栈打印出来,然后分析错误原因,同时让程序继续执行下去 

python内置的logging 模块可以非常容易地记录错误信息:

import logging

def bar1(n):
    return 10/n
def bar2(n):
    return bar1(n)*2
def main():
    try:
        bar2(0)
    except Exception as e:
        logging.exception(e)
main()
print('end')

同样出错,但程序打印完错误信息后会继续执行,并正常退出

ERROR:root:division by zero
end
Traceback (most recent call last):
  File "D:/pythontest/pycharmt/senior/errortest.py", line 9, in main
    bar2(0)
  File "D:/pythontest/pycharmt/senior/errortest.py", line 6, in bar2
    return bar1(n)*2
  File "D:/pythontest/pycharmt/senior/errortest.py", line 4, in bar1
    return 10/n
ZeroDivisionError: division by zero

抛出错误

因为错误是class,捕获一个错误就是捕获到该class的一个实例。因此,错误并不是凭空产生的,而是有意创建并抛出的。python的内置函数会抛出很多类型的错误,我们自己编写的函数也可以

如果要抛出错误,首先要根据需要,定义一个错误的lclass,选择好继承关系,然后用raise语句抛出一个错误的实例

class FooError(ValueError):
    '''错误的类,选择继承关系'''
    pass
def foo(s):
    if s ==0:
        raise FooError('invalid value : %s' % s)#抛出
    return 10/s
foo(0)

执行后,我们最后跟踪对自己定义的错误

Traceback (most recent call last):
  File "D:/pythontest/pycharmt/senior/errortest.py", line 20, in <module>
    foo(0)
  File "D:/pythontest/pycharmt/senior/errortest.py", line 18, in foo
    raise FooError('invalid value : %s' % s)
__main__.FooError: invalid value : 0

只有必要的时候才定义我们自己的错误类型,如果可以你选择python已有的内置的错误类型(比如ValueError,TypeError),尽量使用python内置的错误类型

决不能把一个IOError转换成毫不相干的ValueError

在文档中写清楚可能会抛出那些错误,依旧错误产生的原因

调试

再议logging

把print()替换为logging是检查错误的第三章方式,和assert比,logging不会抛出错误,而且可以输出到文件

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

posted @ 2016-09-01 23:45  notJoke  阅读(316)  评论(0编辑  收藏  举报