数据科学工具箱深度对比:Python和R执行过程的某些特殊情况的异常处理机制)。Python和R作为一种编程语言,自然有自己的异常处理机制。异常处理机制在代码编写中起着非常关键的作用,但却是很多人容易混淆的地方。异常机制的合理使用,直接关系到码农的饭碗!因此,本文将详细介绍Python和R的异常处理机制,阐明两种异常处理机制的异同。异常安全在了解Python和R的异常机制之前,我们需要了解一下异常安全的概念。根据WikiPedia的说法,如果一段代码的运行时故障没有造成有害后果,例如内存泄漏、存储数据混淆或无效输出,那么它就是异常安全的。我们可以知道,一段代码的异常安全性通常分为以下五类:异常安全性通常分为5个等级:故障透明性:如果发生异常,不会进一步向外界抛出。(一般比较复杂)强异常安全:可以运行失败,但数据会回滚到代码运行前(无副作用)基础异常安全:运行失败导致的数据变化,导致代码前后数据不一致runs(withsideeffects)Minimalexception安全性:操作保存无效数据失败,但不会导致崩溃,不会泄露资源(进程不会挂起)异常不安全:无法保证(进程可能会挂起)从以上五个层面来看,我们可以知道,在编写代码的时候,对数据库、文件、网络等的IO操作,需要尽可能做到安全无副作用,即强异常安全.具体来说,RDBS操作失败时需要回滚机制,所有IO操作都必须保证IO连接资源在最后关闭。其实大多数语言的异常机制的语法都是类似的:Python和R都是通过抛出异常对象或者枚举类的值来返回异常;异常处理代码的范围以try开头,以***结尾的一个异常处理子句(catch、except等)结束;几个异常处理子句可以连续出现,每个子句处理一种特定类型的异常。***通过finally子句,不管是否发生异常都会执行,用于释放一些异常处理需要的资源。下面将详细介绍两者的异常处理机制。Python中的异常处理机制首先,Python是一门面向对象的语言。所有的异常类都是通过继承BaseException类来实现的。我们也可以通过相应的继承来实现自定义的异常类,比如在工作流调度中。使用AirflowException,具体实现可以直接看Airflow的源码。其实我们代码处理范围内的这些异常其实可以分为两部分:IO异常:网络抖动、磁盘文件位置变化、数据库连接变化等引起的IO异常运行时异常:运行时发生的异常由于计算或传输时参数类型不正确、参数值异常等,统称为运行时异常。正常情况下,我们对于IO上的异常一定要有相应的try-catch-finally机制,在Python中的实现如下:操作,比如在except中引入APIPOST请求或者数据库写操作,这样如果except阶段出现异常,异常信息就会丢失。另一方面,对于可能出现的运行时异常,我们需要根据具体应用场景的需要进行处理。一般我们遇到一个新问题,都会增加一个新的异常捕获机制。当然,这也考验编码程序。实用主义的设计是否可以未雨绸缪。比如检查数组的长度,检查传入字典的Key等等。Python本身提供了丰富的异常处理类型,易于扩展。正确使用可以显着提高程序的健壮性(保住coder的饭碗)。使用try-catch-finally机制很简单,但混入return和rasie操作后,事情似乎变得有点复杂。举个例子:deftest():try:a=1/0except:a=0raise(ValueError,"valueerror,thedivisionmustgreaterthan0")returnfinally:a=1returnatest()这里的return应该是什么?其实这里的return***应该是1,except里面抛出的exception会被吃掉。这也是一个很好的例子,说明有多少人错误地使用了finanlly。Python在执行带fianlly的子句时,会先缓存except抛出的对象,先执行finally抛出的对象。如果在finally中先抛出return或raise,那么except部分抛出的对象将被Lookseaten。正确的段处理方式应该是这样的:tr??y:doIOinfo={"status":200}except:info={"status":400}finally:try:writelog(info)except:raise(SomeError,"errormessage")closeIO具体的调用栈过程可以参考这个比较形象的例子:R中的异常处理机制R和Python最大的区别在于R本质上是一种强动态类型的非纯函数式编程语言(所谓的非纯纯(即有副作用)而不是面向对象的语言。从函数式编程语言的角度来看,R与Erlang和LISP的关系更密切。既然是函数式语言,处理异常也是函数式的方式,不是直接以面向对象的方式。R从语法上看有点生硬(花括号函数式语言的通病):Python来表达就变成了:try:doStuff()doMoreStuff()exceptSomeException,se:recover(se)其实正确使用R的异常处理机制是一种负担更轻的方式:(R也支持用中文字符集命名的变量)tryCatch({result<-expression},warning=function(w){warning()...#runtimeexception},error=function(e){stop()...#IOexception},最后{on.exit()...#ResourceRecovery}以下是Hadley对R异常处理机制优势的分析:更灵活。事实上,它的灵活性超越了错误处理——条件比异常更通用,因为一个条件可以表示一个y在程序执行期间出现,可能对调用堆栈上不同级别的代码感兴趣。例如,在“条件的其他用途”一节中,您会看到条件可用于发出警告而不会中断g执行发出警告的代码,同时允许调用堆栈上更高的代码来控制是否打印警告消息。然而,目前,我将专注于错误处理。条件系统比异常系统更灵活,因为条件系统不是在发出错误信号的代码和处理它的代码之间提供两部分划分,而是将职责分为三个部分——发出条件信号、处理它和重新启动。在本章中,我将描述如何在一个假设的应用程序中使用条件来分析日志文件。您将看到如何使用条件系统允许低级函数在解析日志文件时检测问题并发出错误信号,以允许中级代码提供几种从此类错误中恢复的可能方法,并允许应用程序最高级别的代码定义e选择使用哪种恢复策略的策略。我的理解是R使用了条件机制,但是我们可以有选择地在低阶函数中吃掉warnings,这样就不会影响到高阶函数的运行了?条件机制将异常分为三个阶段,而不是两个阶段:异常信号捕获异常处理重启机制,我们也可以看到在异常处理中如何在中层函数中恢复低层函数的Error,选择某个高级功能策略中的恢复。这段好像被我误解了,请指正。
