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

翻译:《实用的Python编程》03_03_Error_checking

时间:2023-03-26 15:34:57 Python

类别|上一节(3.2深入功能)|下一节(3.4模块)3.3错误检查虽然之前已经介绍了异常,但本节补充了一些关于错误检查和异常处理细节的其他内容。程序如何失败Python不检查或验证函数参数类型或值。函数可以处理与函数内的语句兼容的任何数据。defadd(x,y):returnx+yadd(3,4)#7add('Hello','World')#'HelloWorld'add('3','4')#如果有错误则为'34',它们将在运行时出现(作为例外)。defadd(x,y):returnx+y>>>add(3,'4')Traceback(mostrecentcalllast):...TypeError:unsupportedoperandtype(s)for+:'int'和'str'>>>为了验证代码,强烈建议进行测试(稍后介绍)。异常异常用于指示错误。要自己引发异常,请使用raise语句:ifnamenotinauthorized:raiseRuntimeError(f'{name}notauthorized')要捕获异常,请使用try-except语句:e:print(e)异常处理异常被传递给第一个匹配except:defgrok():...raiseRuntimeError('Whoa!')#Exceptionraisedheredefspam():grok()#Callthatwillraiseexceptiondefbar():try:spam()exceptRuntimeErrorase:#Exceptioncaughthere...deffoo():try:bar()exceptRuntimeErrorase:#ExceptiondoesNOTarrivehere...foo()想要处理异常,将语句放在except块中。任何处理错误的语句都可以添加到except块中。defgrok():...raiseRuntimeError('Whoa!')defbar():try:grok()exceptRuntimeErrorase:#Exceptioncaughtherestatements#Usethisstatementsstatements...bar()异常处理后,执行从try-except之后的第一条语句继续。defgrok():...raiseRuntimeError('Whoa!')defbar():try:grok()exceptRuntimeErrorase:#Exceptioncaughtherestatementsstatements...statements#Resumesexecutionherestatements#并继续执行...bar()内置异常有很多内置异常。通常,异常名称指示出了什么问题(例如,由于提供了不正确的值而引发了ValueError)。以下列表并非详尽列表,请访问文档以获取更多信息。ArithmeticErrorAssertionErrorEnvironmentErrorEOFErrorImportErrorIndexErrorKeyboardInterruptKeyErrorMemoryErrorNameErrorReferenceErrorRuntimeErrorSyntaxErrorSystemErrorTypeErrorValueErrorExceptions有一个关联值。它包含有关错误的更明确的信息。raiseRuntimeError('Invalidusername')值是异常实例的一部分,放在提供给except的变量中。try:...exceptRuntimeErrorase:#`e`保存引发的异常...e是异常类型的一个实例。但是,打印时,它通常看起来像一个字符串。exceptRuntimeErrorase:print('Failed:Reason',e)捕获多个异常您可以使用多个except块来捕获不同类型的异常:try:...exceptLookupErrorase:...exceptRuntimeErrorase:...exceptIOErrorase:...exceptKeyboardInterruptase:...或者,如果处理不同异常的语句相同,则可以将它们分组:try:...except(IOError,LookupError,RuntimeError)ase:...捕获所有异常要捕获所有异常,请使用Exception。它看起来像这样:try:...exceptException:#危险。见下文print('Anerroroccurred')一般来说,写这样的代码是个坏主意,因为它表明你不知道程序失败的原因。捕获异常的错误方法下面是一种错误的异常使用方法。try:go_do_something()exceptException:print('Computersaysno')这将捕获所有可能的错误,并且当代码由于您没有预料到的原因(例如卸载Python模块等)而失败时可能无法工作调试.更好的方法如果您想捕获所有错误,这里有一个更聪明的方法。try:go_do_something()exceptExceptionase:print('Computersaysno.Reason:',e)报告失败的明确原因。在编写捕获所有可能异常的代码时,拥有一种查看/报告错误的机制几乎总是一个好主意。不过,一般来说,最好尽可能合理地捕获异常。只捕获可以处理的异常。让其他错误通过-也许其他代码可以处理。重新触发异常使用raise来传递捕获的错误。try:go_do_something()exceptExceptionase:print('Computersaysno.Reason:',e)raise这允许您采取行动(例如:记录)并将错误传递给调用者。异常的最佳实践不是捕获异常,而是在发生故障时“停止运行并发出警告”(Failfastandloud)。如果它很重要,其他人会处理它。仅当您是那个人时才捕获异常。即只捕获可以恢复并正常运行的错误。finally语句finally语句指定无论是否发生异常都必须运行的代码。lock=Lock()...lock.acquire()try:...finally:lock.release()#这将始终被执行。无一例外。通常使用finally语句来安全地管理资源(尤其是锁、文件等)。with语句在现代代码中,try-finally语句通常被with语句代替。lock=Lock()withlock:#lockacquired...#lockreleased一个更熟悉的例子:withopen(filename)asf:#Usethefile...#Fileclosed用来。当执行离开上下文时,资源被释放。with语句仅适用于特定编程支持它的特定对象。练习练习3.8:触发异常上一节中编写的parse_csv()函数允许选择用户指定的列,但前提是输入数据文件具有列标题。请修改您的代码以在传递select和has_headers=False参数时触发异常。例如:>>>parse_csv('Data/prices.csv',select=['name','price'],has_headers=False)Traceback(最近调用最后):文件“”,第1行,在File"fileparse.py",line9,inparse_csvraiseRuntimeError("selectargumentrequirescolumnheaders")RuntimeError:selectargumentrequirescolumnheaders>>>添加这个检查后,你可能会问它是否应该在该功能执行其他类型的完整性检查。例如,检查文件名是字符串、列表还是其他?一般来说,最好跳过这样的测试,让程序在输入错误时失败。回溯信息将指向问题的根源并帮助调试。添加上述检查的主要原因是为了避免在无意义的模式下运行代码(例如,使用需要列标题的属性,但同时不指定标题)。这表明调用代码部分存在编程错误。检查“不应该发生”的情况通常是个好主意。练习3.9:捕获异常你编写了parse_csv()函数来处理文件的全部内容。然而,在现实世界中,输入文件可能包含损坏、丢失或脏数据。试试这个实验:>>>portfolio=parse_csv('Data/missing.csv',types=[str,int,float])Traceback(mostrecentcalllast):File"",line1,in文件“fileparse.py”,第36行,在parse_csv行=[func(val)forfunc,valinzip(types,row)]ValueError:invalidliteralforint()withbase10:''>>>请修改parse_csv()函数以捕获记录创建期间生成的所有ValueError异常,并为无法转换的行打印警告消息。错误消息应包括行号和有关失败原因的信息。要测试函数,请尝试阅读上面的Data/missing.csv文件,例如:>>>portfolio=parse_csv('Data/missing.csv',types=[str,int,float])第4行:无法转换['MSFT','','51.23']第4行:以10为底的int()无效文字的原因:''第7行:无法转换['IBM','','70.44']第7行:以10为底数的int()无效文字的原因:''>>>>>>portfolio[{'price':32.2,'name':'AA','shares':100},{'price':91.1,'name':'IBM','shares':50},{'price':83.44,'name':'CAT','shares':150},{'price':40.37,'name':'GE','shares':95},{'price':65.1,'name':'MSFT','shares':50}]>>>练习3.10:隐藏的错误请修改parse_csv()函数,让用户可以显然你可以隐藏解析时的错误信息,例如:>>>portfolio=parse_csv('Data/missing.csv',types=[str,int,float],silence_errors=True)>>>portfolio[{'price':32.2,'name':'AA','shares':100},{'price':91.1,'name':'IBM','shares':50},{'price':83.44,'name':'CAT','份额':150},{'价格e':40.37,'name':'GE','shares':95},{'price':65.1,'name':'MSFT','shares':50}]>>>在大多数程序中,错误处理是最难做好的事情之一。一般来说,不应该默默忽略错误。相反,最好报告问题并让用户选择隐藏错误消息(如果他们愿意)。目录|上一节(3.2深入功能)|NextSection(3.4Modules)注:完整翻译见https://github.com/codists/practical-python-zh

猜你喜欢