如何告诉Mathematica退出调试错误

rjk*_*lan 9 debugging wolfram-mathematica

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

Sjo*_*ies 14

遵循从Mathematica工具包借来的想法:

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

Unprotect[Message];
Message[mm : myMessage::debug] :=
 Block[{$inMsg = True, result},
   Message[mm];
   Quit[]] /; ! TrueQ[$inMsg]
Protect[Message];
Run Code Online (Sandbox Code Playgroud)

在这里,替换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. >> 
*)
Run Code Online (Sandbox Code Playgroud)

你的"调试"消息:

Message[myMessage::debug]

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

 [kernel quits...]
*)
Run Code Online (Sandbox Code Playgroud)

更新

断言消息会获得一些额外的参数,因此您也必须捕获这些参数.顺便说一句,你必须将实际的消息名称放在定义中(不使用我上面使用的示例消息):

Unprotect[Message];
Message[mm : Assert::asrtfl, m___] :=
 Block[{$inMsg = True, result},
   Message[mm, m];
   Quit[]] /; ! TrueQ[$inMsg]
Protect[Message];
Run Code Online (Sandbox Code Playgroud)


WRe*_*ach 8

此响应假定"调试错误"表示已发出消息.例如,如果尝试除以零,则会将消息作为警告发出:

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

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

        ComplexInfinity
Run Code Online (Sandbox Code Playgroud)

注意即使发出警告消息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!";
Run Code Online (Sandbox Code Playgroud)

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

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

         Power::infy: Infinite expression 1/0 encountered. >>
         checkQuit::quit: The kernel is being shut down!
Run Code Online (Sandbox Code Playgroud)

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

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

        Part::partw: Part 10 of {} does not exist. >>
Out[6]= {}[[10]]
Run Code Online (Sandbox Code Playgroud)

请注意,由于消息不匹配,内核是如何退出的Power::infy.但考虑一下:

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

        Power::infy: Infinite expression 1/0 encountered. >>
        checkQuit::quit: The kernel is being shut down!
Run Code Online (Sandbox Code Playgroud)

这里内核退出,因为出现了指示的消息.可以过滤多条消息甚至是预定义的消息组 - 请参阅检查详细信息.


Arn*_*ing 7

除了其他答案,您可能需要调查使用:

$MessagePrePrint
Run Code Online (Sandbox Code Playgroud)

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

例如,您可以评估此​​:

$MessagePrePrint := (Print[Stack[_]]; Dialog[])
Run Code Online (Sandbox Code Playgroud)

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

Return[]
Run Code Online (Sandbox Code Playgroud)

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


Ale*_*kov 5

你写了:

首先,我希望笔记本计算机在出现断言错误时停止运行。

您可以通过$AssertFunction如下定义来做到这一点:

$AssertFunction := Quit[] & ;
Run Code Online (Sandbox Code Playgroud)

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

<< ExampleData`FunctionWithAssert` 
Compute[ 1.0]

(*=> kernel quits*)
Run Code Online (Sandbox Code Playgroud)

另外,您可以使用Interrupt相同的方式:

$AssertFunction := Interrupt[] & ;
Run Code Online (Sandbox Code Playgroud)

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

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

$AssertFunction := (Print[HoldForm @@ #]; Interrupt[]) &;
Run Code Online (Sandbox Code Playgroud)