当前位置: 首页 > 后端技术 > Python

Python基础:Python中的异常和错误

时间:2023-03-26 12:11:14 Python

介绍和其他语言一样,Python也有异常和错误。在Python中,所有异常都是BaseException类的实例。今天我们将详细了解Python中的异常以及如何处理它们。Python中的内置异常类Python中所有的异常类都来自BaseException,它是所有内置异常的基类。虽然它是所有异常类的基类,但是对于用户自定义的类,不建议直接继承BaseException,而是继承Exception。先看一下Python中异常类的结构关系:BaseException+--SystemExit+--KeyboardInterrupt+--GeneratorExit+--Exception+--StopIteration+--StopAsyncIteration+--ArithmeticError|+--浮点错误|+--溢出错误|+--ZeroDivisionError+--AssertionError+--AttributeError+--BufferError+--EOFError+--ImportError|+--ModuleNotFoundError+--查找错误|+--索引错误|+--KeyError+--MemoryError+--NameError|+--UnboundLocalError+--OSError|+--阻塞IO错误|+--子进程错误|+--连接错误||+--破管错误||+--ConnectionAbortedError||+--ConnectionRefusedError||+--连接重置错误|+--文件存在错误|+--FileNotFoundError|中断错误|+--IsADirectoryError|+--NotADirectoryError|+--权限错误|+--ProcessLookupError|+--TimeoutError+--ReferenceError+--RuntimeError|+--未实现错误|+--递归错误+--语法错误|+--缩进错误|+--TabError+--SystemError+--TypeError+--ValueError|+--统一码错误|+--统一码解码错误|+--统一码编码错误|+--UnicodeTranslateError+--Warning+--DeprecationWarning+--PendingDeprecationWarning+--RuntimeWarning+--SyntaxWarning+--UserWarning+--FutureWarning+--ImportWarning+--UnicodeWarning+--BytesWarning+--ResourceWarning其中BaseException,Exception,ArithmeticError,BufferError,LookupError主要被作为其他异常的基础语法错误在Python中,异常和错误通常可以分为两类。第一类是语法错误,也称为解析错误。即,在代码开始运行之前发生的错误。原因是写的代码不符合Python语言规范:>>>whileTrueprint('Helloworld')File"",line1whileTrueprint('Helloworld')^SyntaxError:invalidsyntax上面代码的原因是print前面少了一个冒号。Exception即使我们的程序符合python的语法规范,在执行过程中还是有可能会报错。这种在运行时发送的错误称为异常。查看下面的异常:>>>10*(1/0)Traceback(最近调用最后一次):文件“”,第1行,在ZeroDivisionError:被零除>>>4+spam*3Traceback(最近调用最后):文件“”,第1行,在NameError:name'spam'isnotdefined>>>'2'+2Traceback(最近调用last):文件“",line1,inTypeError:Can'tconvert'int'objecttostrimplicitly异常处理器出现异常怎么办?我们可以使用tryexcept语句来捕获特定的异常。>>>whileTrue:...try:...x=int(input("Pleaseenteranumber:"))...break...exceptValueError:...print("糟糕!那不是validnumber.Tryagain...")...以上代码的执行流程是先执行try中的子语句,如果没有异常发生,则跳过except,完成try语句的执行。如果try中的子语句出现异常,则跳过try子句的后半部分进行异常匹配except。如果匹配成功,则执行except中的子语句。如果发生与except子句中指定的异常不匹配的异常,则将其传递给外部try语句。一个try中可以有多个except子句,我们可以这样写:try:raisecls()exceptD:print("D")exceptC:print("C")exceptB:print("B")oneexcept也可以带多个异常:...except(RuntimeError,TypeError,NameError):...passexcept子句也可以省略异常名称来匹配所有异常:importsystry:f=open('myfile.txt')s=f.readline()i=int(s.strip())exceptOSErroraserr:print("OSerror:{0}".format(err))exceptValueError:print("无法将数据转换为整数.")except:print("Unexpectederror:",sys.exc_info()[0])raisetry...except语句有一个可选的else子句,用在所有except子句的后面时必须放在except子句中。对于当try子句不抛出异常时必须执行的代码很有用。例如:forarginsys.argv[1:]:try:f=open(arg,'r')exceptOSError:print('cannotopen',arg)else:print(arg,'has',len(f.readlines()),'lines')f.close()except可以指定异常变量的名称实例,代表异常实例。我们可以通过instance.args输出异常参数。同时,由于异常实例定义了__str__(),可以直接使用print输出异常的参数。而不是使用.args。让我们看一个例子:>>>try:...raiseException('spam','eggs')...exceptExceptionasinst:...print(type(inst))#异常实例...print(inst.args)#argumentsstoredin.args...print(inst)#__str__allowsargstobedirectly,...#butmaybeoverrideinexceptionsubclasses...x,y=inst.args#解压args...print('x=',x)...print('y=',y)...('spam','eggs')('spam','eggs')x=spamy=eggs在上面的示例中,我们在try子句中抛出异常并指定了2个参数。抛出异常我们可以使用raise语句来抛出异常。>>>raiseNameError('HiThere')Traceback(mostrecentcalllast):File"",line1,inNameError:TheparameterofHiThereraiseisanexception,可以是异常实例,也可以是异常异常类。注意这个异常类必须是Exception的子类。如果传递了一个异常类,就会调用无参构造函数来隐式实例化:raise在except语句中重新抛出异常。>>>try:...raiseNameError('HiThere')...exceptNameError:...print('Anexceptionflushby!')...raise...Anexceptionfloughby!Traceback(最近的calllast):File"",line2,inNameError:HiThereexceptionchain如果我们通过except捕获异常A,我们可以通过raise语句再次抛出不同的异常类型B。那么我们看到的异常信息就是B的信息。但是我们不知道B的异常是从哪里来的。这时候,我们就可以使用异常链了。异常链是当抛出异常时,使用raisefrom语句:>>>deffunc():...raiseIOError...>>>try:...func()...exceptIOErrorasexc:...raiseRuntimeError('Failedtoopendatabase')fromexc...Traceback(最近调用最后):文件“”,第2行,在文件“”,第2行,在funcOSError上面的异常是以下异常的直接原因:Traceback(mostrecentcalllast):File"",line4,inRuntimeError:Failedtoopendatabase在上面的例子中,我们捕捉到IOError之后,并抛出RuntimeError。通过使用异常链,我们可以清楚地看到这两个异常之间的关系。默认情况下,如果从except或finally抛出异常,会自动带上异常链信息。如果您不想采用异常链,可以使用fromNone。try:open('database.sqlite')exceptIOError:raiseRuntimeErrorfromNoneTraceback(mostrecentcalllast):File"",line4,inRuntimeError自定义异常用户可以继承异常来实现自定义的异常,我们看到一些自定义异常的例子:classError(Exception):"""Baseclassforexceptionsinthismodule."""passclassInputError(Error(Error):"""Exceptionraisedforerrorsininput.Attributes:expression--输入发生错误的表达式message--错误解释"""def__init__(self,expression,message):self.expression=expressionself.message=messageclassTransitionError(Error):"""Raised当操作尝试不允许的状态转换时。属性:previous--转换开始时的状态next--尝试的新状态消息--解释为什么不允许特定转换"""def__init__(self,previous,next,信息):self.previous=previousself.next=nextself.message=messagefinallytry语句后面可以跟finally语句来实现一些收尾操作>>>try:...raiseKeyboardInterrupt...finally:...print('Goodbye,world!')...Goodbye,world!KeyboardInterruptTraceback(mostrecentcalllast):File"",line2,infinallyclausewillbeexecutedasthelasttaskbeforetheendoftheendoftheendtry语句,不管try中是否发生异常,都会执行finally语句中的代码。如果finally子句包含return语句,则返回值将来自finally子句的return语句之一的返回值,而不是来自try子句的return语句。>>>defbool_return():...try:...returnTrue...finally:...returnFalse...>>>bool_return()False本文已收录于http://www.flydean.com/09-python-error-exception/最通俗的解读,最深刻的干货,最简洁的教程,很多你不知道的小技巧等你来发现!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!