(MathLink)正确处理从属内核生成的消息

时间:2011-02-14 23:33:27

标签: wolfram-mathematica mathlink

使用从属内核处理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问题。

2 个答案:

答案 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

为了在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]]