第10章 文件和异常——10.3 异常

# -*- coding:utf-8 -*-
#li hongliang 2020年08月13日
#10.3 异常
#Python使用被称为异常的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知所措的错误时,它都会创建一个异常对象。如果你编写了处理该异常的代码,程序将继续运行;如果你未对异常进行处理,程序将停止,并显示一个traceback,其中包含有关异常的报告。异常是使用try-except代码块处理的。try-except代码块让Python执行指定的操作,同时告诉Python发生异常时怎么办。使用了try-except代码块时,即便出现异常,程序也将继续运行:显示你编写的友好的错误消息,而不是令用户迷惑的traceback。

#10.3.1 处理 ZeroDivisionError 异常
''''print(5/0)'''
#ZeroDivisionError: division by zero,该处指出的错误ZeroDivisionError是一个异常对象

#10.3.2 使用 try-except 代码块
#当你认为可能发生了错误时,可编写一个try-except代码块来处理可能引发的异常。你让Python尝试运行一些代码,并告诉它如果这些代码引发了指定的异常,该怎么办。
#division.py
try: 
    print(5/0) 
except ZeroDivisionError: 
    print("You can't divide by zero!")

#我们将导致错误的代码行print(5/0)放在了一个try代码块中。如果try代码块中的代码运行起来没有问题,Python将跳过except代码块;如果try代码块中的代码导致了错误,Python将查找这样的except代码块,并运行其中的代码,即其中指定的错误与引发的错误相同。
#10.3.3 使用异常避免崩溃
#发生错误时,如果程序还有工作没有完成,妥善地处理错误就尤其重要。这种情况经常会出现在要求用户提供输入的程序中;如果程序能够妥善地处理无效输入,就能再提示用户提供有效输入,而不至于崩溃。
#division.py
'''print("Give me two numbers, and I'll divide them.") 
print("Enter 'q' to quit.") 
while True: 
    first_number = input("\nFirst number: ") 
    if first_number == 'q': 
        break 
    second_number = input("Second number: ") 
    if second_number == 'q': 
        break 
    answer = int(first_number) / int(second_number) 
    print(int(answer))'''

#10.3.4 else 代码块
#division.py
'''print("Give me two numbers, and I'll divide them.") 
print("Enter 'q' to quit.") 
while True: 
    first_number = input("\nFirst number: ") 
    if first_number == 'q': 
        break 
    second_number = input("Second number: ") 
    if second_number == 'q': 
        break 
    try:
        answer = int(first_number) / int(second_number) 
    except ZeroDivisionError:
        print("You can't divide by 0!")
    else:
        print(int(answer))'''
#10.3.5 处理 FileNotFoundError 异常
#使用文件时,一种常见的问题是找不到文件:你要查找的文件可能在其他地方、文件名可能不正确或者这个文件根本就不存在。对于所有这些情形,都可使用try-except代码块以直观的方式进行处理。
filename = 'alice.txt'
try: 
    with open(filename) as f_obj: 
        contents = f_obj.read() 
except FileNotFoundError: 
    msg = "Sorry, the file " + filename + " does not exist." 
    print(msg)
#如果文件不存在,这个程序什么都不做,因此错误处理代码的意义不大。下面来扩展这个示例,看看在你使用多个文件时,异常处理可提供什么样的帮助。

#10.3.6 分析文本
#你可以分析包含整本书的文本文件。很多经典文学作品都是以简单文本文件的方式提供的,因为它们不受版权限制。本节使用的文本来自项目Gutenberg(http://gutenberg.org/),这个项目提供了一系列不受版权限制的文学作品,如果你要在编程项目中使用文学文本,这是一个很不错的资源

filename = 'alice.txt'
try:
    with open(filename) as f_obj:
        contents = f_obj.read()
except FileNotFoundError:
    msg = "Sorry, the file " + filename + " does not exist."
    print(msg)
else:
    # 计算文件大致包含多少个单词
    words = contents.split()
    num_words = len(words)
    print("The file " + filename + " has about " + str(num_words) + " words.")

#10.3.7 使用多个文件
#下面多分析几本书。这样做之前,我们先将这个程序的大部分代码移到一个名为count_words()的函数中,这样对多本书进行分析时将更容易:
#word_count.py
"""def count_words(filename):
    #计算一个文件大致包含多少个单词
    try:
        with open(filename) as f_obj:
            contents = f_obj.read()
    except FileNotFoundError:
        msg = "Sorry, the file " + filename + " does not exist."
        print(msg)
    else:
    # 计算文件大致包含多少个单词
        words = contents.split()
        num_words = len(words)
        print("The file " + filename + " has about " + str(num_words) + " words.")
filename = 'alice.txt'
count_words(filename)"""

#现在可以编写一个简单的循环,计算要分析的任何文本包含多少个单词了。为此,我们将要分析的文件的名称存储在一个列表中,然后对列表中的每个文件都调用count_words()。我们将尝试计算Alice in Wonderland、Siddhartha、Moby Dick和Little Women分别包含多少个单词,它们都不受版权限制。我故意没有将siddhartha.txt放到word_count.py所在的目录中,让你能够看到这个程序在文件不存在时处理得有多出色:
'''def count_words(filename):
    """计算一个文件大致包含多少个单词"""
    try:
        with open(filename) as f_obj:
            contents = f_obj.read()
    except FileNotFoundError:
        msg = "Sorry, the file " + filename + " does not exist."
        print(msg)
    else:
    # 计算文件大致包含多少个单词
        words = contents.split()
        num_words = len(words)
        print("The file " + filename + " has about " + str(num_words) + " words.")
filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
for filename in filenames:
    count_words(filename)'''

#在这个示例中,使用try-except代码块提供了两个重要的优点:避免让用户看到traceback;让程序能够继续分析能够找到的其他文件。如果不捕获因找不到siddhartha.txt而引发的FileNotFoundError异常,用户将看到完整的traceback,而程序将在尝试分析Siddhartha后停止运行——根本不分析Moby Dick和Little Women。

#10.3.8 失败时一声不吭
#在前一个示例中,我们告诉用户有一个文件找不到。但并非每次捕获到异常时都需要告诉用户,有时候你希望程序在发生异常时一声不吭,就像什么都没有发生一样继续运行。要让程序在失败时一声不吭,可像通常那样编写try代码块,但在except代码块中明确地告诉Python什么都不要做。Python有一个pass语句,可在代码块中使用它来让Python什么都不要做:
def count_words(filename):
    """计算一个文件大致包含多少个单词"""
    try:
        with open(filename) as f_obj:
            contents = f_obj.read()
    except FileNotFoundError:
        pass
    else:
    # 计算文件大致包含多少个单词
        words = contents.split()
        num_words = len(words)
        print("The file " + filename + " has about " + str(num_words) + " words.")
filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
for filename in filenames:
    count_words(filename)

#相比于前一个程序,这个程序唯一不同的地方是Ø 处的pass 语句。现在, 出现FileNotFoundError异常时,将执行except代码块中的代码,但什么都不会发生。这种错误发生时,不会出现traceback,也没有任何输出。用户将看到存在的每个文件包含多少个单词,但没有任何迹象表明有一个文件未找到:
#pass语句还充当了占位符,它提醒你在程序的某个地方什么都没有做,并且以后也许要在这里做些什么。例如,在这个程序中,我们可能决定将找不到的文件的名称写入到文件missing_files.txt中。用户看不到这个文件,但我们可以读取这个文件,进而处理所有文件找不到的问题。

#10.3.9 决定报告哪些错误
#在什么情况下该向用户报告错误?在什么情况下又应该在失败时一声不吭呢?如果用户知
#道要分析哪些文件,他们可能希望在有文件没有分析时出现一条消息,将其中的原因告诉他们。
#如果用户只想看到结果,而并不知道要分析哪些文件,可能就无需在有些文件不存在时告知他们。
#向用户显示他不想看到的信息可能会降低程序的可用性。Python的错误处理结构让你能够细致地
#控制与用户分享错误信息的程度,要分享多少信息由你决定。
#编写得很好且经过详尽测试的代码不容易出现内部错误,如语法或逻辑错误,但只要程序依
#赖于外部因素,如用户输入、存在指定的文件、有网络链接,就有可能出现异常。凭借经验可判
#断该在程序的什么地方包含异常处理块,以及出现错误时该向用户提供多少相关的信息。

              #动手试一试
#10-6 加法运算:提示用户提供数值输入时,常出现的一个问题是,用户提供的是
#文本而不是数字。在这种情况下,当你尝试将输入转换为整数时,将引发TypeError 异
#常。编写一个程序,提示用户输入两个数字,再将它们相加并打印结果。在用户输入的
#任何一个值不是数字时都捕获TypeError 异常,并打印一条友好的错误消息。对你编写
#的程序进行测试:先输入两个数字,再输入一些文本而不是数字。
"""print("Give me two numbers, and I'll add them.") 
print("Enter 'q' to quit.") 
while True: 
    first_number = input("\nFirst number: ") 
    if first_number == 'q': 
        break 
    second_number = input("Second number: ") 
    if second_number == 'q': 
        break 
    try:
        add = int(first_number) + int(second_number) 
    except ValueError:
        print("Can't convert 'str' object to int implicitly")
    else:
        print(int(add))"""

#10-7 加法计算器:将你为完成练习10-6 而编写的代码放在一个while 循环中,让
#用户犯错(输入的是文本而不是数字)后能够继续输入数字。
'''10-6代码与10-7相同'''

#10-8 猫和狗:创建两个文件cats.txt 和dogs.txt,在第一个文件中至少存储三只猫的
#名字,在第二个文件中至少存储三条狗的名字。编写一个程序,尝试读取这些文件,并
#将其内容打印到屏幕上。将这些代码放在一个try-except 代码块中,以便在文件不存
#在时捕获FileNotFound 错误,并打印一条友好的消息。将其中一个文件移到另一个地
#方,并确认except 代码块中的代码将正确地执行。

"""读取以下文件"""
filenames = ["cats.txt","dogs.txt"]
for filename in filenames:
    try:
        with open(filename) as object:
            contents = object.read()
    except FileNotFoundError:
        msg = "Sorry, the file " + filename + " does not exist."
        print(msg)
    else:
        filename = contents.split()
        print(filename)  
         
#10-9 沉默的猫和狗:修改你在练习10-8 中编写的except 代码块,让程序在文件不
#存在时一言不发。

filenames = ["cats.txt","dogs.txt"]
for filename in filenames:
    try:
        with open(filename) as object:
            contents = object.read()
    except FileNotFoundError:
        pass
    else:
        filename = contents.split()
        print(filename) 

#10-10 常见单词:访问项目Gutenberg(http://gutenberg.org/),并找一些你想分析的
#图书。下载这些作品的文本文件或将浏览器中的原始文本复制到文本文件中。
#你可以使用方法count()来确定特定的单词或短语在字符串中出现了多少次。例如,
#下面的代码计算'row'在一个字符串中出现了多少次:
#>>> line = "Row, row, row your boat"
#>>> line.count('row')
#2
#>>> line.lower().count('row')
#3
#请注意,通过使用lower()将字符串转换为小写,可捕捉要查找的单词出现的所有
#次数,而不管其大小写格式如何。
#编写一个程序,它读取你在项目Gutenberg 中获取的文件,并计算单词'the'在每
#个文件中分别出现了多少次。

def count_words_the(filename):  #定义函数
    """计算一个文件大致包含多少个单词"""
    try:
        with open(filename) as f_obj:
            contents = f_obj.read()
    except FileNotFoundError:
        msg = "Sorry, the file " + filename + " does not exist."
        print(msg)
    else:
    # 计算文件大致包含多少个单词
        the = contents.lower().count('the')
        print("The file " + filename + " has about " + str(the) + " the.")
filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
for filename in filenames:
    count_words_the(filename)   #调用函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值