Python基础教程之异常详解

一、摘要

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

异常是使用try-except 代码块处理的。try-except 代码块让Python执行指定的操作,同时告诉Python发生异常时怎么办。使用了try-except 代码块时,即便出现异常,程序也将继续运行:显示你编写的友好的错误消息,而不是令用户迷惑的traceback

二、异常实操

处理ZeroDivisionError 异常:try-except&try-except-else

在上述traceback中,指出的错误ZeroDivisionError 是一个异常对象。Python无法按你的要求做时,就会创建这种对象。在这种情况下,Python将停止运行程序,并指出引发了哪种异常,而我们可根据这些信息对程序进行修改。下面我们将使用try-except告诉Python,发生这种错误时怎么办

将导致错误的代码行print(5/0) 放在了一个try 代码块中。如果try 代码块中的代码运行起来没有问题,Python将跳过except 代码块;如果try 代码块中的代码导致了错误,Python将查找这样的except 代码块,并运行其中的代码,即其中指定的错误与引发的错误相同,在这个示例中,try 代码块中的代码引发了ZeroDivisionError 异常,因此Python指出了该如何解决问题的except 代码块,并运行其中的代码。这样,用户看到的是一条友好的错误消息,而不是traceback,如果try-except 代码块后面还有其他代码,程序将接着运行,因为已经告诉了Python如何处理这种错误

使用异常避免崩溃:

发生错误时,如果程序还有工作没有完成,妥善地处理错误就尤其重要。这种情况经常会出现在要求用户提供输入的程序中;如果程序能够妥善地处理无效输入,就能再提示用户提供有效输入,而不至于崩溃。

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(answer)

这个程序没有采取任何处理错误的措施,因此让它执行除数为0的除法运算时,它将崩溃:

Give me two numbers, and I'll divide them.
Enter 'q' to quit.
First number: 5
Second number: 0
Traceback (most recent call last):
 File "division.py", line 9, in <module>
  answer = int(first_number) / int(second_number)
ZeroDivisionError: division by zero

程序崩溃可不好,但让用户看到traceback也不是好主意。不懂技术的用户会被它们搞糊涂,而且如果用户怀有恶意,他会通过traceback获悉你不希望他知道的信息。例如,他将知道你的程序文件的名称,还将看到部分不能正确运行的代码。有时候,训练有素的攻击者可根据这些信息判断出可对你的代码发起什么样的攻击。

通过将可能引发错误的代码放在try-except 代码块中,可提高这个程序抵御错误的能力。错误是执行除法运算的代码行导致的,因此我们需要将它放到try-except 代码块中。这个示例还包含一个else 代码块;依赖于try 代码块成功执行的代码都应放到else 代码块中:

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: ")
 try:
  answer = int(first_number) / int(second_number)
 except ZeroDivisionError:
  print("You can't divide by 0!")
 else:
  print(answer)

让Python尝试执行try 代码块中的除法运算,这个代码块只包含可能导致错误的代码。依赖于try 代码块成功执行的代码都放在else 代码块中;在这个示例中,如果除法运算成功,我们就使用else 代码块来打印结果。except 代码块告诉Python,出现ZeroDivisionError 异常时该怎么办。如果try 代码块因除零错误而失败,我们就打印一条友好的消息,告诉用户如何避免这种错误。程序将继续运行,用户根本看不到traceback:

Give me two numbers, and I'll divide them.
Enter 'q' to quit.
First number: 5
Second number: 0
You can't divide by 0!
First number: 5
Second number: 2
2.5
First number: q

try-except-else 代码块的工作原理大致如下:Python尝试执行try 代码块中的代码;只有可能引发异常的代码才需要放在try 语句中。有时候,有一些仅在try 代码块成功执行时才需要运行的代码;这些代码应放在else 代码块中。except 代码块告诉Python,如果它尝试运行try 代码块中的代码时引发了指定的异常,该怎么办。通过预测可能发生错误的代码,可编写健壮的程序,它们即便面临无效数据或缺少资源,也能继续运行,从而能够抵御无意的用户错误和恶意的攻击。

处理FileNotFoundError 异常:

使用文件时,一种常见的问题是找不到文件:你要查找的文件可能在其他地方、文件名可能不正确或者这个文件根本就不存在。对于所有这些情形,都可使用try-except 代码块以直观的方式进行处理

filename = 'alice.txt'
with open(filename) as f_obj:
 contents = f_obj.read()

当我们尝试打开的文件(alice.txt)不存在时,python会报如下异常:

Traceback (most recent call last):
 File "alice.py", line 3, in <module>
  with open(filename) as f_obj:
FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt' 

在上述traceback中,最后一行报告了FileNotFoundError 异常,这是Python找不到要打开的文件时创建的异常。在这个示例中,这个错误是函数open() 导致的,因此要处理这个错误,必须将try 语句放在包含open() 的代码行之前:

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)

分析文本:

split()函数,看看下边的例子,这个函数干了什么

>>> title = "Alice in Wonderland"
>>> title.split()
['Alice', 'in', 'Wonderland']

split() 以空格为分隔符将字符串分拆成多个部分,并将这些部分都存储到一个列表中。结果是一个包含字符串中所有单词的列表,虽然有些单词可能包含标点。为计算Alice in Wonderland 包含多少个单词,我们将对整篇小说调用split() ,再计算得到的列表包含多少个元素,从而确定整篇童话大致包含多少个单词

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.")

将文件alice.txt移到了正确的目录中,让try 代码块能够成功地执行。对变量contents (它现在是一个长长的字符串,包含童话 Alice in Wonderland 的全部文本)调用方法split() ,以生成一个列表,其中包含这部童话中的所有单词。当我们使用len() 来确定这个列表的长度时,就知道了原始字符串大致包含多少个单词,我们打印一条消息,指出文件包含多少个单词,这些代码都放在else 代码块中,因为仅当try 代码块成功执行时才执行它们。输出指出了文件alice.txt包含多少个单词

使用多个文件:

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)

然后编写一个循环,调用这个函数让他分析多个文件:

filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
for filename in filenames:
 count_words(filename)

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

在前一个示例中,我们告诉用户有一个文件找不到。但并非每次捕获到异常时都需要告诉用户,有时候你希望程序在发生异常时一声不吭,就像什么都没有发生一样继续运行。要让程序在失败时一声不吭,可像通常那样编写try 代码块,但在except 代码块中明确地告诉Python什么都不要做。Python有一个pass 语句,可在代码块中使用它来让Python什么都不要做

def count_words(filename):
"""计算一个文件大致包含多少个单词"""
 try:
  --snip--
 except FileNotFoundError:
  pass
 else:
  --snip--
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中。用户看不到这个文件,但我们可以读取这个文件,进而处理所有文件找不到的问题

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Python 错误和异常小结

    事先说明哦,这不是一篇关于Python异常的全面介绍的文章,这只是在学习Python异常后的一篇笔记式的记录和小结性质的文章.什么?你还不知道什么是异常,额... 1.Python异常类 Python是面向对象语言,所以程序抛出的异常也是类.常见的Python异常有以下几个,大家只要大致扫一眼,有个映像,等到编程的时候,相信大家肯定会不只一次跟他们照面(除非你不用Python了). 异常 描述 NameError 尝试访问一个没有申明的变量 ZeroDivisionError 除数为0 Synt

  • Python标准异常和异常处理详解

    python提供了两个非常重要的功能来处理python程序在运行中出现的异常和错误.你可以使用该功能来调试python程序. 1.异常处理: 本站Python教程会具体介绍. 2.断言(Assertions):本站Python教程会具体介绍. python标准异常 异常名称 描述 BaseException 所有异常的基类 SystemExit 解释器请求退出 KeyboardInterrupt 用户中断执行(通常是输入^C) Exception 常规错误的基类 StopIteration 迭代

  • 深入理解python try异常处理机制

    深入理解python try异常处理机制 #python的try语句有两种风格 #一:种是处理异常(try/except/else) #二:种是无论是否发生异常都将执行最后的代码(try/finally) try/except/else风格 try: <语句> #运行别的代码 except <名字>: <语句> #如果在try部份引发了'name'异常 except <名字>,<数据>: <语句> #如果引发了'name'异常,获得附

  • python中的五种异常处理机制介绍

    从几年前开始学习编程直到现在,一直对程序中的异常处理怀有恐惧和排斥心理.之所以这样,是因为不了解.这次攻python,首先把自己最畏惧和最不熟悉的几块内容列出来,里面就有「异常处理」这一项. <Dive into Python>并没有专门介绍异常处理,只是例子中用到的时候略微说明了一下.今天下载<Learn Python>,直接进异常处理这块.这一部分有四章,第一章讲解异常处理的一般使用方法,后面的章节深入地讨论其机制.我目前只看了第一章,先学会用,以后有必要的时候再扩展阅读. p

  • 处理Python中的URLError异常的方法

    1.URLError 首先解释下URLError可能产生的原因: 网络无连接,即本机无法上网 连接不到特定的服务器 服务器不存在 在代码中,我们需要用try-except语句来包围并捕获相应的异常.下面是一个例子,先感受下它的风骚 import urllib2 requset = urllib2.Request('http://www.xxxxx.com') try: urllib2.urlopen(requset) except urllib2.URLError, e: print e.rea

  • Python 异常处理实例详解

    一.什么是异常?异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行.一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误.当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行.二.异常处理捕捉异常可以使用try/except语句.try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理.如果你不想在异常发生时结束你的程序,只需在try里捕获它. 异常语法:以下为简单的try....

  • Python异常处理总结

    本文较为详细的罗列了Python常见的异常处理,供大家参考,具体如下: 1. 抛出异常和自定义异常 Python用异常对象(exception object)表示异常情况,遇到错误后,会引发异常.如果异常对象并未被处理或捕捉,程序就会用所谓的回溯(Traceback,一种错误信息)终止执行. ①.raise 语句 Python中的raise 关键字用于引发一个异常,基本上和C#和Java中的throw关键字相同,如下所示: # -- coding: utf-8 -- def ThorwErr()

  • 浅谈python抛出异常、自定义异常, 传递异常

    一. 抛出异常 Python用异常对象(exception object)表示异常情况,遇到错误后,会引发异常.如果异常对象并未被处理或捕捉,程序就会用所谓的回溯(Traceback,一种错误信息)终止执行. raise 语句 Python中的raise 关键字用于引发一个异常,基本上和C#和Java中的throw关键字相同,如下所示: import traceback def throw_error(): raise Exception("抛出一个异常")#异常被抛出,print函数

  • 零基础写python爬虫之HTTP异常处理

    先来说一说HTTP的异常处理问题. 当urlopen不能够处理一个response时,产生urlError. 不过通常的Python APIs异常如ValueError,TypeError等也会同时产生. HTTPError是urlError的子类,通常在特定HTTP URLs中产生. 1.URLError 通常,URLError在没有网络连接(没有路由到特定服务器),或者服务器不存在的情况下产生. 这种情况下,异常同样会带有"reason"属性,它是一个tuple(可以理解为不可变的

  • 详解在Python程序中自定义异常的方法

    通过创建一个新的异常类,程序可以命名它们自己的异常.异常应该是典型的继承自Exception类,通过直接或间接的方式. 以下为与RuntimeError相关的实例,实例中创建了一个类,基类为RuntimeError,用于在异常触发时输出更多的信息. 在try语句块中,用户自定义的异常后执行except块语句,变量 e 是用于创建Networkerror类的实例. class Networkerror(RuntimeError): def __init__(self, arg): self.arg

随机推荐