Python基础教程之异常详解


Posted in Python onJanuary 10, 2019

一、摘要

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

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

二、异常实操

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

Python基础教程之异常详解

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

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中。用户看不到这个文件,但我们可以读取这个文件,进而处理所有文件找不到的问题

总结

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

Python 相关文章推荐
python笔记(2)
Oct 24 Python
python 实现上传图片并预览的3种方法(推荐)
Jul 14 Python
python获取网页中所有图片并筛选指定分辨率的方法
Mar 31 Python
python高级特性和高阶函数及使用详解
Oct 17 Python
python使用matplotlib画柱状图、散点图
Mar 18 Python
Python面向对象程序设计类的封装与继承用法示例
Apr 12 Python
python爬虫神器Pyppeteer入门及使用
Jul 13 Python
对django的User模型和四种扩展/重写方法小结
Aug 17 Python
Python @property使用方法解析
Sep 17 Python
Python中的X[:,0]、X[:,1]、X[:,:,0]、X[:,:,1]、X[:,m:n]和X[:,:,m:n]
Feb 13 Python
关于python3.9安装wordcloud出错的问题及解决办法
Nov 02 Python
python 写一个水果忍者游戏
Jan 13 Python
Python+OpenCV感兴趣区域ROI提取方法
Jan 10 #Python
python+opencv 读取文件夹下的所有图像并批量保存ROI的方法
Jan 10 #Python
pandas ix &amp;iloc &amp;loc的区别
Jan 10 #Python
python 移动图片到另外一个文件夹的实例
Jan 10 #Python
python将处理好的图像保存到指定目录下的方法
Jan 10 #Python
对python PLT中的image和skimage处理图片方法详解
Jan 10 #Python
python pandas库的安装和创建
Jan 10 #Python
You might like
PHP Array交叉表实现代码
2010/08/05 PHP
php 地区分类排序算法
2013/07/01 PHP
一款简单实用的php操作mysql数据库类
2014/12/08 PHP
PHP中Laravel 关联查询返回错误id的解决方法
2017/04/01 PHP
PHP实现广度优先搜索算法(BFS,Broad First Search)详解
2017/09/16 PHP
基于CI(CodeIgniter)框架实现购物车功能的方法
2018/04/09 PHP
利用404错误页面实现UrlRewrite的实现代码
2008/08/20 Javascript
javascript中文本框中输入法切换的问题
2013/12/10 Javascript
使用JS获取当前地理位置方法汇总
2014/12/18 Javascript
jQuery实现Meizu魅族官方网站的导航菜单效果
2015/09/14 Javascript
JavaScript触发onScroll事件的函数节流详解
2016/12/14 Javascript
ionic开发中点击input时键盘自动弹出
2016/12/23 Javascript
js弹性势能动画之抛物线运动实例详解
2017/07/27 Javascript
jQuery实现轮播图及其原理详解
2020/04/12 jQuery
JavaScript函数的4种调用方法实例分析
2019/03/05 Javascript
JavaScript基于面向对象实现的无缝滚动轮播示例
2020/01/17 Javascript
搭建vscode+vue环境的详细教程
2020/08/31 Javascript
python实现文件快照加密保护的方法
2015/06/30 Python
浅谈Python peewee 使用经验
2017/10/20 Python
详解Django中类视图使用装饰器的方式
2018/08/12 Python
利用 Flask 动态展示 Pyecharts 图表数据方法小结
2019/09/04 Python
python的scipy实现插值的示例代码
2019/11/12 Python
在Keras中实现保存和加载权重及模型结构
2020/06/15 Python
python3爬虫中引用Queue的实例讲解
2020/11/24 Python
python实现猜拳游戏项目
2020/11/30 Python
Brookstone美国官网:独特新奇产品
2017/03/04 全球购物
美国知名平价彩妆品牌:e.l.f. Cosmetics
2017/11/20 全球购物
铭万公司.net面试题笔试题
2014/07/20 面试题
一篇.NET面试题
2014/09/29 面试题
群众路线自我剖析范文
2014/11/04 职场文书
2014财务年度工作总结
2014/11/11 职场文书
就业推荐表导师评语
2014/12/31 职场文书
工作表扬信范文
2015/01/17 职场文书
酒店工程部岗位职责
2015/02/12 职场文书
医学会议开幕词
2016/03/03 职场文书
MySQL的prepare使用以及遇到的bug
2022/05/11 MySQL