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

发布于 2024-10-17 12:55:39 字数 1327 浏览 3 评论 0原文

当使用从属内核处理 MathLink 时,我在正确解析 TextPacket 时遇到问题。特别是当这样的数据包对应于从属内核生成的Message时,我根本不明白如何正确处理它。我需要在评估笔记本中打印这样的消息,就好像它们是由主内核生成的一样(但有一些标记以表明它来自从属内核)。我需要将与 Message 对应的 TextPacket 与仅 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;

但我认为应该有更直接的解决方案。特别是在以这种方式处理时,我得到了带有 HoldFormTextPacket

TextPacket[Power::infy: Infinite expression HoldForm[0^(-1)] encountered.]

我不知道如何将此类字符串转换为适合作为 Message 打印的形式

PS这个问题来自那个问题。

When working through MathLink with slave kernel I have a problem with correct parsing TextPackets. In particular when such packet corresponds to a Message generated by the slave kernel I do not understand how to handle it correctly at all. I need such Messages to be printed in the evaluation notebook as if they were generated by master kernel (but with some mark to make clear that it comes from the slave). And I need to separate TextPackets corresponding to Messages from just to Print[] commands. The latter I need to parse correctly too, printing them in the evaluation notebook with a little mark that it is from the slave kernel.

Here is an example of what happens:

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]]

The Message by default comes through MathLink in the form:

TextPacket[                                 1
Power::infy: Infinite expression - encountered.
                                 0]

It looks ugly. The only way to make it better I have found is to evaluate in the slave kernel

$MessagePrePrint = InputForm;

But I think there should be more straightforward solution. In particular when dealing this way I get TextPackets with HoldForms inside:

TextPacket[Power::infy: Infinite expression HoldForm[0^(-1)] encountered.]

I do not know how to convert such string into a form appropriate for printing as a Message.

P.S. This question comes from that question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半山落雨半山空 2024-10-24 12:55:39

我想分享 Todd Gayley(Wolfram Research)针对给定问题提出的一个很好的技巧。也许对某人有用,对我也有用。这个技巧以相当优雅的方式解决了所讨论的问题。

一种技术是离开
OutputForm 处的 FormatType 为
计算,但覆盖
暂时处理消息
切换到 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]
           ]
        ]]

您将得到一个包含 a 内容的 ExpressionPacket
信息。要将其打印为消息单元格中的
笔记本:

cell = Cell[, "Message", "MSG"]
细胞打印[细胞]

高级方法:所有内容都打印在 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];

I would like to share a nice hack proposed by Todd Gayley (Wolfram Research) in connection with the given question. Perhaps for somebody it will be useful as also for me. This hack solves the problem in question in rather elegant way.

One technique is to leave the
FormatType at OutputForm for
computations, but override the
handling of Message to temporarily
switch to StandardForm, so that only
Message output comes back in
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]
           ]
        ]]

You will get back an ExpressionPacket for the content of a
message. To print that as a Message cell in the
notebook:

cell = Cell[<the ExpressionPacket>, "Message", "MSG"]
CellPrint[cell]

Advanced approach: everything is printed in the StandardForm

For having everything except output returned in StandardForm we could redefine variables $Pre and $Post in the slave kernel in a special way (the following code should be evaluated in the slave kernel):

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];
苍风燃霜 2024-10-24 12:55:39

该表达式始终以 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]]

The expression comes in HoldForm always, but with the default $MessagePrePrint it is not
rendered. Try evaluating

HoldForm[1/0]

InputForm[%]

One way to achieve your desired behavior would be to implement your own box renderer. To see that the renderer has to process, set

$MessagePrePrint = ToBoxes[{##}] &

in the slave. Like so:

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]]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文