技术标签: python 异常 [软件开发]python
Python用异常对象(exception object)来表示异常情况。遇到错误后,会引发异常。若异常对象未被处理或捕捉,程序会用回溯(Traceback,一种错误信息)终止执行,例如:
>>> 1/0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
事实上,每个异常都是一些类的实例,可以被引发也可以被捕捉。当捕捉到这些异常并对其进行处理,可使程序继续运行。
学习处理异常之前,先学习如何引发异常,以及自定义异常类型。
可以使用一个类(Exception的子类)或实例参数调用raise语句来引发异常。当使用类时,程序会自动创建实例。例如:
#引发没有错误信息的普通异常
>>> raise Exception
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Exception
#添加错误信息的异常
>>> raise Exception("hyperdrive overload")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Exception: hyperdrive overload
内建的异常类有很多种(参考Python库参考手册的“Build-in Exception”一节),这些异常都可以在exceptions模块(和内建的命名空间)中找到,所有这些异常都可以用在raise语句中。
>>> import exceptions
>>> dir(exceptions)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError', 'EnvironmentError', 'Exception', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__doc__', '__name__', '__package__']
下表描述了一些重要的内建异常类:
类名 | 描述 |
---|---|
Exception | 所有异常的基类 |
AttributeError | 特性引用或赋值失败时引发 |
IOError | 试图打开不存在文件(包括其他情况)时引发 |
IndexError | 在使用序列中不存在的索引时引发 |
KeyError | 在使用映射中不存在的键时引发 |
NameError | 再找不到名字(变量)时引发 |
SyntaxError | 在代码为错误形式时引发 |
TypeError | 在内建操作或者函数应用于错误类型的对象时引发 |
ValueError | 在内建操作或者函数应用于正确类型的对象,但是该对象使用不合适的值时引发 |
ZeroDivisionError | 在除法或者模除操作的第二个参数为0时引发 |
自定义异常类可以根据异常所在的类,选择性地处理当前类型的异常。
创建异常类与创建其他类方法一样,只需确保从Exception类继承即可。
可以使用try/except实现捕捉异常并作错误处理,例如:
>>> try:
... x=input('enter the first number: ')
... y=input('enter the second number: ')
... print x/y
... except ZeroDivisionError:
... print "The second number can't be zero!"
...
enter the first number: 10
enter the second number: 0
The second number can't be zero!
上述异常也可以通过if语句检查y值实现,但是try/except有以下优势:
1. 若出现多个除法运算,需要对所有运算进行if判断,而是用try/except只需要一个错误处理器;
2. try/except不会搞乱原来的代码,而if语句检查可能错误会降低代码可读性。
★若异常没有被捕捉,将会被传递到调用的函数中,直到程序最顶层
若捕捉到的函数想重新引发,可以使用不带参数的raise。例如,定义一个可以屏蔽ZeroDivisionError异常的类:
>>> class MuffledCalculator:
... muffled=False
... def calc(self, expr):
... try:
... return eval(expr)
... except ZeroDivisionError:
... if self.muffled:
... print "Division by zero is illegal"
... else:
... raise
使用示例如下:
>>> calculator=MuffledCalculator()
>>> calculator.calc("10/2")
5
>>> calculator.calc("10/0") #屏蔽未打开,捕捉并重新引发ZeroDivisionError异常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in calc
File "<string>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
>>> calculator.muffled=True
>>> calculator.calc("10/0") #屏蔽被打开,打印错误信息
Division by zero is illegal
8.3节中的第一个例子,若在提示符后面输入非数字类型的值,会产生另一个异常:
enter the first number: w
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<string>", line 1, in <module>
NameError: name 'w' is not defined
可以在try/except后添加另一个except子句,用于捕捉另一个异常:
>>> try:
... x=input('enter the first number: ')
... y=input('enter the second number: ')
... print x/y
... except ZeroDivisionError:
... print "The second number can't be zero!"
... except TypeError:
... print "That wasn't a number, was it?"
...
enter the first number: 23
enter the second number: "That wasn't a number, was it?"
That wasn't a number, was it?
若要用一个块捕捉多个异常类型,可以将它们作为元组列出。例如:
>>> try:
... x=input('enter the first number: ')
... y=input('enter the second number: ')
... print x/y
... except (ZeroDivisionError, TypeError, NameError):
... print "Your numbers were bogus..."
...
若希望在except子句中访问异常对象本身,可以使用两个参数。例如,如果希望程序继续运行,但是又想记录错误时,可能用到该功能。
>>> try:
... x=input('enter the first number: ')
... y=input('enter the second number: ')
... print x/y
... except (ZeroDivisionError, TypeError, NameError), e:
... print e
...
enter the first number: 34
enter the second number: aa
name 'aa' is not defined
可以使用try/except指定要捕捉的异常类型,但是,程序员无法预测所有可能发生的异常,总会有所遗漏。可以在except子句中忽略所有的异常类,以实现捕捉所有异常:
>>> try:
... x=input('enter the first number: ')
... y=input('enter the second number: ')
... print x/y
... except:
... print "Something wrong happened..."
...
enter the first number: 34
enter the second number: a
Something wrong happened...
!!!捕捉所有异常类是危险的,他会隐藏所有程序员未想到并且为做好准备处理的错误。甚至会捕捉用户中止执行的Ctrl+C操作,以及用sys.exit函数终止程序的操作。此时可以使用except Exception, e,或者对异常对象e进行一些检查。
之前的例子中,发生异常后往往只打印一个错误信息,对于产生的异常没有实际修正作用。上述例子可以像对条件和循环语句那样,给try/except添加else子句实现循环,实现只有在没有异常情况下退出,否则重新执行异常语句的功能。例如:
>>> while True:
... try:
... x=input("enter the first number: ")
... y=input("enter the second number: ")
... print x/y
... except Exception, e: #捕获所有异常并保存到e
... print "invalid input: ",e #打印捕获的异常
... print "Please input again" #若有异常,则重新执行
... else: #若没有异常,只想下面一行代码,退出循环
... break
...
enter the first number: 1
enter the second number: 0
invalid input: integer division or modulo by zero
Please input again
enter the first number: dds
invalid input: name 'dds' is not defined
Please input again
enter the first number: "asd"
enter the second number: "nmm"
invalid input: unsupported operand type(s) for /: 'str' and 'str'
Please input again
enter the first number: 10
enter the second number: 2
5
finally子句,用于try/except之后的清理工作,无论是否发生异常,都会执行finally子句。例如:
>>> try:
... 1/1 #无异常发生时
... except:
... print "except"
... finally:
... print "finally"
...
1
finally
>>> try:
... 1/0 #有异常发生时
... except:
... print "except"
... finally:
... print "finally"
...
except
finally
finally子句在代码执行后关闭文件或者套接字是非常有用。
在Python2.5之前,finally子句需要独立使用,不能作为try/except子句使用。在Python2.5及其之后版本中,可以与try/except/else/finally组合使用。
若异常在函数内引发而不被处理,它就会被传递到函数调用的地方。若调用处没有被处理,它会继续传播,一直到达主程序(全局作用域)。若依然没有被处理,程序会带着堆栈跟踪中止。例如:
>>> def faulty():
... raise Exception("Something is wrong")
...
>>> def ignore_faulty():
... faulty()
...
>>> def handle_exception():
... try:
... faulty()
... except:
... print "Exception handled"
...
>>> ignore_faulty() #faulty的异常传递到ignore_faulty,未处理异常,导致堆栈跟踪
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in ignore_faulty
File "<stdin>", line 2, in faulty
Exception: Something is wrong
>>> handle_exception() #faulty的异常传递到handle_exception,被处理
Exception handled
异常处理并不是很复杂。若知道某段代码可能导致某种异常,又不希望程序已堆栈跟踪的形式终止,可以根据需要添加try/except或try/finally语句进行处理。
有时条件语句可以实现和异常处理同样的功能,但条件语句可能在自然性和可读性上差些。另一方面看,某程序使用if/else实现会比使用try/except要好。
举个例子对比下if/else和try/except。假设有一个字典,希望打印出存储在特定的键下面的值。若不存在,则什么也不做。
可以使用if/else实现,编码如下:
>>> def describePerson(person):
... print "Description of", person["name"]
... print "Age:", person["age"]
... if "occupation" in person:
... print "Occupation:", person["occupation"]
#提供名字和年龄字典时的输出
>>> holly={
"name":"holly","age":55}
>>> describePerson(holly)
Description of holly
Age: 55
#提供名字、年龄和职业时的输出
>>> holly={
"name":"holly","age":55, "occupation":"software engineer"}
>>> describePerson(holly)
Description of holly
Age: 55
Occupation: software engineer
上述代码直观,但效率低。程序会两次查找“occupation”键——判断是否存在;获取键值。
可以采用try/except语句实现,编码如下:
>>> def describePerson(person):
... print "Description of", person["name"]
... print "Age:", person["age"]
... try:
... print "Occupation:" + person["occupation"]#此处使用加号连接,若使用逗号,发生异常时"occupation:"会被输出
... except KeyError: pass
...
#提供名字和年龄字典时的输出
>>> holly={
"name":"holly","age":55}
>>> describePerson(holly)
Description of holly
Age: 55
#提供名字、年龄和职业时的输出
>>> holly={
"name":"holly","age":55, "occupation":"software engineer"}
>>> describePerson(holly)
Description of holly
Age: 55
Occupation:software engineer
程序假定”occupation”键存在,若真实存在,则直接输出打印;否则会引发KeyError异常,被except捕捉处理。
另一个例子,展示下try/except在查看对象是否存在某特性中的作用。假设要查看某对象是否有write特性,编码如下:
>>> try:
... obj.write
... except AttributeError:
... print "The object is not writeable"
... else:
... print "The objece is writebale"
try子句访问特性,若引发AttributeError异常,说明对象没这个特性,反之有。这跟getattr方法功能相同,事实上getattr内部实现也是使用了该方法。
★上述代码获得的效率提高并不多,除非程序对性能有明确需求,否则开发人员不需要过多考虑优化的问题。
★很多情况下,使用try/except比使用if/else更加”Python化”,应养成尽可能使用try/except语句。
★try/except语句在Python中的表现可以用海军少将Grace Hooper的妙语解释:”请求宽恕易于请求许可”。在做一件事时去处理可能出现的错误,而不是在开始做事前就进行大量的检查,这个可略可以总结为习语”看钱就调(Leap Before You Look)”。
查看ServiceEntrypackage mainimport ( "context" "log" "github.com/owenliang/k8s-client-go/common" "istio.io/api/networking/v1beta1" networkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" versionedclient "istio.io/client-go/pkg/clientset/
编辑docker的配置文件vim /etc/docker/daemon.json{ "registry-mirrors": ["https://kuamavit.mirror.aliyuncs.com", "https://registry.docker-cn.com", "https://docker.mirrors.ustc.edu.cn"], "max-concurrent-downloads": 10, "storage-driver": "overlay2", "grap_start-limit-hit
从CSV文件中读取数据,去掉内容中的逗号,打印到屏幕。生成ls的方法不同,效果有所差别import jsonf = open("学生信息表.csv","r",encoding = 'gbk')ls = []for line in f : line = line.replace("\n","") ls = line.split(",") print(ls)f.close()运行结果为:[‘学号’, ‘姓名’, ‘性别’, ‘班级’][‘17010001’, ‘张三_open("info.csv", 'r',encoding='gbk')
大概率导错包了。在使用DruidDataSource连接MySQL时,连接失败,报错com.alibaba.druid.pool.DruidPooledConnection cannot be cast to sun.rmi.transport.Connection。我的原因是导入了错误的包。正确的应该是import java.sql.Connection;..._com.alibaba.druid.pool.druidpooledpreparedstatement.executequery(druidpooled
函数式接口只含有一个抽象方法的接口,称为函数式接口。lambda表达式可以赋值并且仅可以赋值给函数式接口的变量。实际上编译器往往需要根据函数式接口推断lambda表达式的参数类型和返回值,比如:Comparator comp = (first, second) -> Integer.compare(first.length(), second.length())。实际上,你甚至无法将一个lam_写给大忙人的se8
Ⅰ.通过仓库名获取文件列表import requestsimport json# 文件列表 参数 仓库名称 返回code 200# 请求方式: GETurl = '192.168.1.111:8081'auth = ("admin", "admin123")res = requests.get( url='http://{0}/service/rest/v1/components'.format(url), params={"repository": "test"}, _nexus制品列表查询树状展开接口
已知两个非降序链表序列S1与S2,设计函数构造出S1与S2合并后的新的非降序链表S3。输入格式:输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−表示序列的结尾(−不属于这个序列)。数字用空格间隔。输出格式:在一行中输出合并后新的非降序链表,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL。输入样例:1 3 5 -12 4 6 ..._7-2 两个有序链表序列的合并
# This is a customized agent init file that contains the HS parameters# that are needed for the Database...
首先引入okhttp框架 compile 'com.squareup.okhttp3:okhttp:3.7.0' compile 'com.squareup.okio:okio:1.13.0'GET请求private void demo1() { try { //get请求的参数拼在url后,需要编码,同时服务器也需要解码 String url ="http:..._使用浏览器访问https://txd.m.taobao.com/app/locallife/tbmc-app-home/shop-
2021计算机网络形考作业一(附答案) 计算机网络形考作业一(附答案) 一、选择题 题目1 计算机网络的功能有()。选择一项: A. 用户管理 B. 站点管理 C. 病毒管理 D. 资源共享 题目分析: 计算机网络的功能有:(1)资源共享;(2)数据通信;(3)集中管理;(4)增加可靠性;(5)提高系统的处理能力和安全功能。其中,资源共享和数据通信是计算机网络最基本的两大功能。 题目2 网络资源子..._计算机网络项目作业
当我们建立springboot的项目的时候,通常第一步导入依赖这时你有可能遇到projec报红这个问题主要是你下面的某个依赖没有引入成功因为maven库找不到对应的版本如果你没有给这个依赖加上version,建议加上,如果加上了建议换成更稳定的版本..._springboot propenties 文件 爆红
DateFormatDateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间。SimpleDateFormatSimpleDateFormat是一个以与语言环境有关的方式来格式化和解析日期的具体类。DateTimeFormatter 对 LocalDateTime进行格式化Date date = newDate();date.setYear(118);..._tue sep 04 23:13:40 cst 2018 java 格式化