Message Boards Message Boards

4
|
5896 Views
|
3 Replies
|
9 Total Likes
View groups...
Share
Share this post:

Run NotebookEvaluate on a "slave" kernel controlled through MathLink?

Posted 8 years ago

I am evaluating commands on a "slave kernel" which I control from a "master kernel" through MathLink in a manner similar to this:

The slave kernel is of a different (older) version than the master.

I want to evaluate

UsingFrontEnd[NotebookEvaluate[..., InsertResults -> True]]

on the slave, but it doesn't work: it simply hangs. If I run the same in a terminal, i.e. with a kernel not controlled through MathLink and $ParentLink not set, it works. UsingFrontEnd operations which do require a front end but do not require that front end to call back to the kernel also work.

I am not surprised that this doesn't work, I imagine the subsidiary front end gets into trouble when it tries to call back to its kernel, as the parent link of that kernel is taken. I don't understand the details.

But is there an easy solution to this? Or should I better give up?

Why do I want this? I want to process some documentation notebooks in a the oldest version of Mathematica that the package is compatible with. I am trying to automate all this and I have a function which can launch a subsidiary Mathematica process of the requested version and evaluate various things with it.

POSTED BY: Szabolcs Horvát
3 Replies

I've struggled with NotebookEvaluate[] as well when run from a subkernel. One of my workarounds for simpler notebooks is to write my own "NotebookEvaluate" function:

1) read the raw form of the notebook using Get

2) replace every Input cell type with a sequence of Input and Output cells, where the Output cell has gone from its BoxForm, ToExpression, and back to BoxForm.

evaluateNotebook[loc_String] := Module[{test,nb},
  UsingFrontEnd[
    test=Get[loc];
    nb=CreateDocument[test/.Cell[BoxData[x___],"Input",y___] :> Sequence[Cell[BoxData[x],"Input",y],Cell[BoxData[ToBoxes[ToExpression[BoxData[x]]]],"Output"]]];
    NotebookSave[nb,loc];
    NotebookClose[nb];
  ]
]

This will not overwrite older Output or warning messages, but you can add some rules to remove those, too, using empty sequences:

  (*rule to remove old output cells*)
  Cell[BoxData[___], "Output", ___] -> Sequence[]; 

  (*rules to remove old message cells*)
  Cell[BoxData[___], "Message", ___] -> Sequence[]; 

I'm not sure how robust this approach is, i.e. I haven't tested how it deals with cells that are commented out, but it does a good job for how short it is. I'm open to any feedback on improving it.

POSTED BY: Kevin Daily

You are right. At this point my vague impression is that it is generally safer to manipulate notebook expressions using the kernel rather than the Front End, even though the Front End way tends to be much more convenient.

POSTED BY: Szabolcs Horvát

I need to correct what I said. Doing this causes hang only in version 9.0.1 and 10.0.2, but not in 10.3.1, 10.4.1 or 11.0.1.

However, there is a problem in recent versions too: the subsidiary kernel process does not terminate after closing the link. It hangs around indefinitely.

Let me give a concrete example:

Start a kernel:

link = LinkLaunch["\"" <> First[$CommandLine] <> "\" -mathlink"];
LinkRead[link]; (*read initial prompt*)

Send the evaluation:

LinkWrite[link,
 Unevaluated@EvaluatePacket[
   UsingFrontEnd[
    nb = CreateDocument[{Cell["1+1", "Input"]}];
    NotebookEvaluate[nb, InsertResults -> True];
    NotebookGet[nb]
    ]
   ]
 ]

In 10.0.2 at this point the subsidiary kernel stops responding. In v11 we can continue:

In[4]:= LinkRead[link]

Out[4]= ReturnPacket[
 Notebook[{Cell[
    CellGroupData[{Cell["1+1", "Input"], 
      Cell[OutputFormData["2"], "Output", 
       CellChangeTimes -> {3.6894*10^9}]}, Open]]}, 
  WindowSize -> {808, 751}, 
  WindowMargins -> {{316, Automatic}, {Automatic, 50}}, 
  FrontEndVersion -> 
   "11.0 for Mac OS X x86 (32-bit, 64-bit Kernel) (September 21, \
2016)", StyleDefinitions -> "Default.nb"]]

As you can see, the evaluation succeeded, and I got back a notebook expression.

Now let's close the link:

LinkClose[link]

At this point the link becomes invalid. However, the process on the other end of the link doesn't terminate. Neither does the front end it has launched. I must kill it using kill -9 as a simple kill won't do it.

Luckily there is a workaround. Instead of LinkClose, just send a Quit[]:

LinkWrite[link, Unevaluated@EvaluatePacket[Quit[]]]

And then close: LinkClose[link].

Question: Is there a way to make this work in version 10.0, even if it requires some hacks?

Why do I need this? I want to process some documentation notebooks precisely with a selected version of Mathematica. This is to avoid the "InsufficientVersionWarning" on the users' computers. What I really need is using a front end of a given version, not a kernel. So if there's a way to use a v10.0 kernel from v11.0 without going through a v10.0 kernel, that would be a workable solution for me.

POSTED BY: Szabolcs Horvát
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract