(MathLink)正确处理从内核生成的消息
当通过MathLink
与奴隶内核工作时,我正确解析TextPacket
有问题。 特别是当这样的数据包对应于从内核产生的Message
,我不明白如何正确处理它。 我需要将这些Messages
打印在评估笔记本中,就好像它们是由内核生成的一样(但有一些标记表明它来自从机)。 我需要将TextPacket
对应的Message
从简单的Print[]
命令中分离出来。 后者我也需要正确解析,将它们打印在评估笔记本中,并带有一点来自从内核的标记。
以下是发生情况的一个例子:
link = LinkLaunch[First[$CommandLine] <> " -mathlink"]
Print@LinkRead[link]
LinkWrite[link,
Unevaluated[EnterExpressionPacket[Print[a]; 1/0; Print[b]]]]
While[Not@MatchQ[packet = LinkRead[link], InputNamePacket[_]],
Print[packet]]
默认情况下, Message
通过MathLink
以下面的形式出现:
TextPacket[ 1
Power::infy: Infinite expression - encountered.
0]
它看起来很丑。 让我更好的唯一方法是在slave内核中进行评估
$MessagePrePrint = InputForm;
但我认为应该有更直接的解决方案。 特别是在处理这种方式时,我在里面使用HoldForm
获得TextPacket
:
TextPacket[Power::infy: Infinite expression HoldForm[0^(-1)] encountered.]
我不知道如何将这样的字符串转换为适合打印为Message
的格式。
PS这个问题来自于这个问题。
我想分享一个由Todd Gayley(Wolfram Research)提出的关于给定问题的很好的黑客攻击。 也许对某个人来说,它也会对我有用。 这种破解以相当优雅的方式解决了问题。
一种方法是将FormatType保留在OutputForm中进行计算,但重写Message的处理以临时切换到StandardForm,以便只有消息输出返回到StandardForm中:
LinkWrite[link,
Unevaluated[EnterExpressionPacket[
Unprotect[Message];
Message[args___]:=
Block[{$inMsg = True, result},
SetOptions[$Output, FormatType->StandardForm];
result = Message[args];
SetOptions[$Output, FormatType->OutputForm];
result
] /; !TrueQ[$inMsg]
]
]]
你将得到一个消息内容的ExpressionPacket。 要在笔记本中将其打印为消息单元格:
cell = Cell[<the ExpressionPacket>, "Message", "MSG"]
CellPrint[cell]
高级方法:所有内容都打印在StandardForm中
除了在StandardForm
返回输出外,我们还可以用特殊方式在slave内核中重新定义变量$Pre
和$Post
(以下代码应在从内核中进行评估):
SetOptions[$Output, {PageWidth -> 72, FormatType -> StandardForm}];
(*$inPost is needed for tracing mode compatibility
(could be switched on by evaluating On[] in the slave kernel)
in which Messages are printed during evaluation of $Post.*)
$inPost = False; Protect[$inPost];
$Pre := Function[inputexpr,
SetOptions[$Output, FormatType -> StandardForm];
Unevaluated[inputexpr], HoldAllComplete];
$Post := Function[outputexpr,
Block[{$inPost = True},
SetOptions[$Output, FormatType -> OutputForm];
Unevaluated[outputexpr]], HoldAllComplete];
Protect[$Pre]; Protect[$Post];
$inMsg = False; Protect[$inMsg];
Unprotect[Message];
Message[args___] /; $inPost := Block[{$inMsg = True},
SetOptions[$Output, FormatType -> StandardForm];
Message[args];
SetOptions[$Output, FormatType -> OutputForm]] /; ! $inMsg;
Protect[Message];
表达式始终在HoldForm中,但是默认的$ MessagePrePrint不会被渲染。 尝试评估
HoldForm[1/0]
InputForm[%]
实现你想要的行为的一种方法是实现你自己的盒子渲染器。 看到渲染器必须处理,设置
$MessagePrePrint = ToBoxes[{##}] &
在奴隶。 像这样:
link = LinkLaunch[First[$CommandLine] <> " -mathlink"]
Print@LinkRead[link]
LinkWrite[link,
Unevaluated[
EnterExpressionPacket[$MessagePrePrint = ToBoxes[{##}] &; Print[a];
1/0; Print[b]]]]
While[Not@MatchQ[packet = LinkRead[link], InputNamePacket[_]],
Print[packet]]
链接地址: http://www.djcxy.com/p/35499.html
上一篇: (MathLink) Correct handling of Messages generated by slave kernel
下一篇: Splitting a list based on another list values in Mathematica