如何告诉Mathematica退出调试错误

时间:2011-11-02 20:52:39

标签: debugging wolfram-mathematica

在Mathematica中是否有一个设置(我希望它是一个环境变量)会导致内核在发生调试错误时退出?通常,我会收到调试错误,笔记本将继续评估错误的数据,迫使我重新启动内核。

4 个答案:

答案 0 :(得分:14)

遵循从Mathematica toolbag借来的想法:

myMessage::debug = "Something went horribly wrong";

Unprotect[Message];
Message[mm : myMessage::debug] :=
 Block[{$inMsg = True, result},
   Message[mm];
   Quit[]] /; ! TrueQ[$inMsg]
Protect[Message];

在此处,将myMessage::debug替换为您要拦截的实际邮件类型。

正常消息:

Message[Power::infy]

(* ===> 
        StringForm::sfr: Item 1 requested in "Infinite expression `1` 
        encountered. >>" out of range; 0 items available. >> 

        Power::infy: Infinite expression `1` encountered. >> 
*)

您的“调试”消息:

Message[myMessage::debug]

(* ===>
myMessage::debug: Something went horribly wrong

 [kernel quits...]
*)

更新

断言消息会获得一些额外的参数,所以你也必须抓住它们。顺便说一下,你必须将实际的消息名称放在定义中(不使用我上面使用的示例消息):

Unprotect[Message];
Message[mm : Assert::asrtfl, m___] :=
 Block[{$inMsg = True, result},
   Message[mm, m];
   Quit[]] /; ! TrueQ[$inMsg]
Protect[Message];

答案 1 :(得分:8)

此响应假设“调试错误”表示已发出Message。例如,如果尝试除以零,则会将消息作为警告发出:

In[1]:= Print[1/0]

        Power::infy: Infinite expression 1/0 encountered. >>

        ComplexInfinity

注意ComplexInfinity语句如何Print打印,即使发出了警告消息,也表明计算在“错误”之后仍在继续。

我不会重新讨论@ Sjoerd的优秀答案,该答案显示了如何配置Mathematica会话,以便在任何评估发出任何消息时内核将退出。如果您希望更具选择性并且仅在特定评估发出消息时退出内核,则以下函数可能有用:

ClearAll[checkQuit]
SetAttributes[checkQuit, HoldFirst]
checkQuit[expr_, HoldPattern[messages_:Sequence[]]] :=
  Check[expr, Message[checkQuit::quit]; Quit[], messages]
checkQuit::quit = "The kernel is being shut down!";

有了这个定义,你可以在特定评估发出任何消息后强制内核退出:

In[37]:= checkQuit[Print[1/0]]

         Power::infy: Infinite expression 1/0 encountered. >>
         checkQuit::quit: The kernel is being shut down!

如果发出某些消息,如果只是退出内核可能会很方便。为此,checkQuit接受可选的第二个参数,该参数可用于指定感兴趣的消息:

In[6]:= checkQuit[{}[[10]], Power::infy]

        Part::partw: Part 10 of {} does not exist. >>
Out[6]= {}[[10]]

请注意,由于消息与Power::infy不匹配,内核未退出。但请考虑:

In[7]:= checkQuit[1/0, Power::infy]

        Power::infy: Infinite expression 1/0 encountered. >>
        checkQuit::quit: The kernel is being shut down!

此处内核退出,因为出现了指示的消息。可以过滤多条消息甚至是预定义的消息组 - 有关详细信息,请参阅Check

答案 2 :(得分:7)

除了其他答案,您可能需要使用以下方式进行调查:

$MessagePrePrint

允许您在触发任何消息时执行代码。

例如,您可以对此进行评估:

$MessagePrePrint := (Print[Stack[_]]; Dialog[])

打印正在评估的代码的评估堆栈(有时非常大!)。然后,对话框功能将您置于子评估循环中,允许您检查值 变量。要退出对话框循环,您可以评估:

Return[]

将您带回主循环(主要评估然后完成或中断 在新消息)。

答案 3 :(得分:5)

您写道:

  

首先,我希望我的笔记本停止运行断言   错误。

您可以按照以下方式定义$AssertFunction来执行此操作:

$AssertFunction := Quit[] & ;

现在内核在断言失败时退出:

<< ExampleData`FunctionWithAssert` 
Compute[ 1.0]

(*=> kernel quits*)

或者,您可以以相同的方式使用Interrupt

$AssertFunction := Interrupt[] & ;

它允许您中止评估或输入subsession(与Arnoud的答案中的Dialog[]相同)。

您还可以扩展此方法来打印失败的断言:

$AssertFunction := (Print[HoldForm @@ #]; Interrupt[]) &;