使用从属内核处理MathLink
时,我遇到了正确解析TextPacket
的问题。特别是当这样的数据包对应于从内核生成的Message
时,我根本不理解如何正确处理它。我需要在评估笔记本中打印这样的Messages
,好像它们是由主内核生成的(但是有一些标记以表明它来自从属)。我需要将TextPacket
s对应的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]
看起来很难看。我发现改善它的唯一方法是在从属内核中进行评估
$MessagePrePrint = InputForm;
但我认为应该有更直接的解决方案。特别是当以这种方式处理时,我得到TextPacket
s里面有HoldForm
s:
TextPacket[Power::infy: Infinite expression HoldForm[0^(-1)] encountered.]
我不知道如何将此类字符串转换为适合以Message
打印的形式。
P.S。这个问题来自that问题。
答案 0 :(得分:4)
我想与Todd Gayley(Wolfram Research)分享一个与给定问题有关的好的黑客。也许对某些人来说,它对我来说也很有用。这个hack以相当优雅的方式解决了问题。
一种技巧是离开 OutputForm的FormatType for 计算,但覆盖 暂时处理消息 切换到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
中返回除输出之外的所有内容,我们可以以特殊方式重新定义从属内核中的变量$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];
答案 1 :(得分:2)
该表达式总是在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]]