Jeffrey Cross
Jeffrey Cross

Codebox:处理Processing中的异常

在Codebox中:将传感器数据保存到Google Spreadsheets,读者Stairs观察到当他没有连接Arduino设备时草图爆炸了。当他挖出设备,将其插入并重新启动草图时,它工作正常。

这说明了处理,编程和生活的一个重点:我们生活在一个不完美的世界。漂亮的小草图开始时没有插入Arduino,数字除以零,人们用剪刀运行,依此类推。在处理中,调用这些条件 例外,这篇文章提供了如何处理的温和介绍(或更正式的, 处理)他们。 (注意:这篇文章不会阻止用剪刀跑。)

那么,首先,如果出现问题,Processing会如何让您知道?一般情况下(除非出现严重错误!),您将启动草图,然后看到类似下图的内容:

注意消息区域中的所有红色错误消息,这是Processing告诉您出错的地方。在这种情况下,错误是 PortInUseException(),如果你开始谷歌搜索,你会发现在加工中有一些格格不入的声誉。 (稍后会详细介绍。)该消息还会告诉您错误在哪一行 抛出。此外,违规行在文本编辑器中以黄色突出显示。根据错误发生的位置,草图窗口可能会或可能不会出现,即使它是可见的,它几乎肯定不会达到您的预期。

要重现此错误(或类似的错误 - 请参阅帖子底部的警告部分!),将simple_port.pde的文本粘贴到Processing中。如果一切顺利,草图会每秒读取一次串行端口,并显示已用时间和从端口读取的值。

当然,我们并不希望一切顺利(这是本文的重点),因此请确保在运行草图时拔掉Arduino。你应该看到类似上图的东西。现在我们准备添加代码来处理(或 处理,这是正式术语)断开连接的设备。

要处理Processing(和Java,其中Processing是子集)中的异常,我们将可疑代码放在“try-catch-finally”块中。然后处理“尝试”执行代码,如果抛出任何异常,它们将被其他块“捕获”。语法如下所示:

尝试{ 您想要尝试执行的可疑代码 ...} catch(ExceptionType1 e1){ //如果在try块中抛出ExceptionType1,则执行代码 的println(e1.getMessage()); ...} catch(ExceptionType1 e2){ //如果在try块中抛出ExceptionType2,则执行代码 的println(e2.getMessage()); ...} catch(ExceptionType3 e3){ //如果在try块中抛出ExceptionType3,则执行代码 的println(e3.getMessage()); ......}终于{ //在这里清理代码 ... }

由于处理入门中未涉及异常,因此,让我回答您可能遇到的一些常见问题:

  • 你是什​​么意思 可疑代码? 最初,您可能认为所有代码都是可疑的,但异常处理主要用于几个关键环境,例如读取或写入文件,通过网络提取数据或与设备通信(如串行端口)。实际上,许多库要求您在try-catch块中包含某些方法,否则代码根本不会编译。例如,如果您从google电子表格代码中删除了try块,则该程序甚至无法编译。图书馆设计师这样做是为了迫使程序员养成良好习惯。
  • 所有这些捕获陈述是关于什么的?由于代码可能以各种方式出错,我们需要能够处理许多不同的可能性。因此,每个catch语句都与一种特定类型的错误相关联。如果发生该特定类型的错误,则执行相应的代码块。例如,假设您尝试从文件中读取一些数据。该文件可能不存在,抛出一个 FileNotFoundException异常 例外。或者,该文件可能存在,但在您阅读时会以某种方式变得不可用。这引发了 EOFException类。或者,在IO流中发生了一些非常奇怪的事情,这会产生冰雹 IOException异常。您可以为每种情况创建一个catch块。也许最好的比喻是“入门”一书第64页中描述的if-then-else块。
  • 捕获后括号中的内容是什么意思?这些类似于函数的参数 - 第一个标记标识应该导致块触发的异常类型,第二个标记是允许您访问异常的数据和方法的变量。 (异常,就像Processing中的所有内容一样,都是对象。)例如,如果你有这样的一行 - catch(FileNotFoundException e),如果try块中的代码找不到您要查找的文件,则该块将执行。在块中,您将有一个名为的变量 Ë 您可以用来了解更多关于出错的地方。例如,您可以使用它 的getMessage() 将错误的详细信息输出到消息区域的方法
  • catch语句的顺序是否重要?是。 Processing将触发与异常的类或超类匹配的第一个catch块。由于对象是分层的,这意味着某些例外在食物链中比其他例外更高。因此,它们几乎匹配所有东西。 (调用排名最高的异常类 例外,它匹配所有内容。)因此,您需要先将最具体的类型排除,然后再放置更常见的异常。
  • “终于”是什么意思?该 最后 block是可选的,允许您添加代码 总是 执行,是否发生错误。这通常用于清理代码。例如,如果您打开文件,则可能需要在finally块中关闭它。
  • 如果我的catch块中没有确切的错误类型怎么办?简短的回答是你的程序爆炸了。这是一种情况,称为 未处理的异常,通常是你想要避免的。作为最后的捕获,你可以简单地添加一个 catch(例外e) 作为最后的拦截块。这是最通用的异常对象类型,因此它应该捕获大多数错误。

呼。足够的理论。让我们回到阻止我们的代码爆炸的原始问题。 (尽管如此,我们只是表面上看。如果你想了解更多信息,请查看课程:例外,Oracle的一个很棒的教程。)

因为我们的代码正在爆炸 port = new Serial(this,arduinoPort,9600);,这是放置try-catch块的一个非常明显的地方。我们希望代码执行的是测试此行上是否有任何异常(我们并不关心什么),如果有,则显示“插入Arduino”消息。一旦插入Arduino,我们就想开始显示计数器和串口的当前值。这是代码的修订版本simple_port2.pde,它可以做到这一点。

运行此代码时,您应该看到类似下图的内容。

那么,这里发生了什么?你会注意到的第一件事是我把违规的线移出了 建立() 方法并入 画() 方法。这确保草图将反复测试是否找到Arduino;在做测试 建立() 意味着它只会在草图开始时发生一次。接下来,我创建了一个名为的标志 ardinoOK - 如果此标志为false,我们想尝试获取端口并显示错误消息。如果标志为真,那么我们想要读取端口并显示值。最后,我已经嵌入了 port = new Serial(this,arduinoPort,9600); try-catch块内的一行。如果命令成功,那么我们设置 arduinoOK 为真。如果发生异常,我们会抓住它 catch(例外e) 阻止和设置 arduinoOK 为假。因为这段代码在里面 画(),它一遍又一遍地重复这个逻辑。瞧!

注意事项

正如我在整个过程中暗示的那样,该项目的异常处理有点难以处理。例如,Stairs(评论开始这篇文章的读者)报道了一个 ArrayIndexOutOfBoundsExeption。这意味着代码正在爆炸 String arduinoPort = Serial.list()[0]:,表明没有设备。 “哈,”我想,我只是测试那个例外。但是,当我在我的Mac上运行它时,我发现列表中已经有几个设备,所以它并没有因为楼梯的错误而被炸毁。 Arduino中的插件只是在列表中添加了两个新项目,如下表所示。

没有安装Arduino Arduino安装
稳定的库========================================= Native lib Version = RXTX-2.1 -7 Java lib Version = RXTX-2.1-7 [0]“/ dev /tty.Bluetooth-Modem”[1]“/ dev / cu.Bluetooth-Modem”[2]“/ dev /tty.Bluetooth-PDA-同步“[3]”/dev/cu.Bluetooth-PDA-Sync“ 稳定的库========================================= Native lib Version = RXTX-2.1 -7 Java lib Version = RXTX-2.1-7 [0]“/ dev/tty.usbmodem1d11”[1]“/dev/cu.usbmodem1d11”[2]“/ dev /tty.Bluetooth-Modem”[3]“ /dev/cu.Bluetooth-Modem“[4]”/dev/tty.Bluetooth-PDA-Sync“[5]”/ dev / cu.Bluetooth -PDA-Sync“实验:JNI_OnLoad调用。

一些谷歌搜索表明Mac默认运行几个进程来接收新设备,如相机或蓝牙设备。所以,我认为楼梯必须在PC上,没有这些物品。

但是,我的代码仍在爆炸,但是出现了不同的错误: gnu.io.PortInUseException。 “哈!”但是,我可以抓住那一个。但是,这也行不通。谷歌搜索,我发现在OS X上似乎有一个奇怪的错误,使得捕获此异常成为问题,并且您必须重新安装或删除串行库的各个部分才能使它们正常工作。所以,这也没有用。最后,我刚刚决定抓住最通用的 例外 让它工作。

然后,我想更多地了解在草图运行时如何捕获错误。具体来说,我想处理Arduino插入的情况,草图开始运行,然后你在中途拔掉它。但是,当我尝试这个时,我得到了这个错误消息,似乎来自操作系统:

由于它在食物链中被处理得更高,因此错误从未作为例外流入Processing,所以草图只是快乐地哼唱着。嗯,我想。因此,一些谷歌搜索显示,做我计划的事情是非常糟糕的,并且它可能导致各种各样的问题。所以,我猜Mac内置了安全措施来防止下游问题。我想我应该感恩,但是这个例子让我感到沮丧。

所有这些都表明,确定编程错误确实非常非常困难,因为存在很多复杂性和相互依赖性。我想这可能是为什么这么多程序员成为Makers的原因。在一个6个月可以永恒的职业中,知道你用齿轮和杠杆制造的机器可能是亚里士多德可以理解的,这是令人满意的。坦率地说,令人难以置信的是,世界运行得如此顺利。

谢谢各地的异常处理程序!

在Maker Shed中:


处理入门使用Processing学习计算机编程的简单方法,这是一种简单的语言,可让您使用代码创建绘图,动画和交互式图形。编程课程通常从理论开始,但本书可以让您直接进入创造性和有趣的项目。它是任何想要学习基本编程的人的理想选择,并且可以为具有一些编程技能的人提供简单的图形介绍。

分享

发表评论