如何从命令行评估笔记本?

发布于 2024-12-23 16:03:46 字数 1023 浏览 2 评论 0原文

我们如何从命令行评估 Mathematica 笔记本(即在命令行模式下运行内核时)?

假设我们正在远程计算机上工作。我知道可以将笔记本转换为 m 文件并对其进行评估,但我很好奇是否可以直接使用笔记本来执行此操作。


这是我到目前为止所拥有的:

首先,我们需要在远程启动一个无头 X 服务器 Linux机器,所以前端可以在那里运行(并打开笔记本)。如果您在本地计算机上工作,请跳过此步骤。

Xvfb :1 &
export DISPLAY=:1

之后,我启动了 Mathematica 内核 (math) 并执行了以下操作。

有必要使用 UsingFrontEnd 因为打开笔记本需要前端。 test.nb 有一个包含 a=1 的输入单元格。

In[1]:= nb=UsingFrontEnd@NotebookOpen["test.nb"]

Out[1]= -NotebookObject-

尝试评估笔记本后,显然我得到了一个 对话框,我需要使用 Return[] 返回。我不确定为什么输入行再次从 1 开始计数(前端启动了一个新内核?)请注意,a 没有获得值。

In[2]:= UsingFrontEnd@NotebookEvaluate[nb]

 In[1]:= a

 Out[1]= a

 In[2]:= Return[]

Out[2]= a

从对话框返回后,a 仍然没有值。

In[3]:= a

Out[3]= a

How can we evaluate a Mathematica notebook from the command line (i.e. when running the kernel in command line mode)?

Suppose we're working on a remote machine. I know it is possible to convert the notebook to an m-file, and evaluate that, but I'm curious if it's possible to do this directly using the notebook.


This is what I have so far:

First, we need to start a headless X server on the remote Linux machine, so the front end can run there (and open the notebook). Skip this step if you're working on a local machine.

Xvfb :1 &
export DISPLAY=:1

After this I started a Mathematica kernel (math) and did the following.

It's necessary to use UsingFrontEnd because opening notebook requires a front end. test.nb has a single input cell containing a=1.

In[1]:= nb=UsingFrontEnd@NotebookOpen["test.nb"]

Out[1]= -NotebookObject-

After trying to evaluate the notebook, apparently I get a dialog, and I need to use Return[] to return. I am not sure why the input line starts counting from 1 again (a new kernel was started by the front end?) Note that a didn't gain a value.

In[2]:= UsingFrontEnd@NotebookEvaluate[nb]

 In[1]:= a

 Out[1]= a

 In[2]:= Return[]

Out[2]= a

After returning from the dialog, a still doesn't have a value.

In[3]:= a

Out[3]= a

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

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

发布评论

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

评论(2

故事还在继续 2024-12-30 16:03:46

这是对你问题的部分回答。以下代码打开一个笔记本,为其分配一个
“测试”内核,评估该内核中的笔记本,等待评估完成并
保存评估的笔记本。不过,它不会导致a在本地命令行内核中定义。

这将等待笔记本中的内核评估完成:

NotebookPauseForEvaluation[nb_] := Module[{},
 While[ NotebookEvaluatingQ[nb], Pause[.25] ] ]

这将检查笔记本中的任何单元是否仍在评估中:

NotebookEvaluatingQ[nb_]:=Module[{},
 SelectionMove[nb,All,Notebook];
 Or@@Map["Evaluating"/.#&,Developer`CellInformation[nb]]
]

这只是一条诊断消息,当您尝试重新定义“测试”之类的内核时:

AddTestEvaluator::exists = "Evaluator `1` is already defined, but has a definition that is `2` and not the expected `3`.";

这是要添加的代码评估器,例如前端的“测试”:

AddTestEvaluator[evaluator_String] := Module[
 {evaluatornames, testevaluator},
 evaluatornames = EvaluatorNames /. Options[$FrontEnd, EvaluatorNames];
 testevaluator = evaluator -> {"AutoStartOnLaunch" -> False};
 Which[
  MemberQ[evaluatornames, evaluator -> {"AutoStartOnLaunch" -> False}],
  Null,
  MemberQ[evaluatornames, evaluator -> _],
  Message[AddTestEvaluator::exists,
  evaluator,
  evaluator /. (EvaluatorNames /. Options[$FrontEnd, EvaluatorNames]),
  {"AutoStartOnLaunch" -> False}
 ],
 True,
 AppendTo[evaluatornames, testevaluator];
 SetOptions[$FrontEnd, EvaluatorNames -> evaluatornames]
 ]
]

最后,这是在“测试”内核下评估笔记本并保存评估后的内核的代码:

 UsingFrontEnd[     
  AddTestEvaluator["Test"];
  nb = NotebookOpen["test.nb"];
  SetOptions[nb,Evaluator->"Test"];
  SelectionMove[nb,All,Notebook];
  SelectionEvaluate[nb];
  NotebookPauseForEvaluation[nb];
  NotebookSave[nb]
 ]

我仍在寻找针对您的完整问题的解决方案(具有 a 本地命令中定义的
线内核)。

This is a partial answer to your question. The following code opens a notebook, assigns it a
"Test" kernel, evaluates the notebook in that kernel, waits for the evaluation to finish and
saves the evaluated notebook. It does not cause a to be defined in the local command line kernel though.

This waits for kernel evaluations to finish in the notebook:

NotebookPauseForEvaluation[nb_] := Module[{},
 While[ NotebookEvaluatingQ[nb], Pause[.25] ] ]

This checks if any cell in the notebook is still under evaluation:

NotebookEvaluatingQ[nb_]:=Module[{},
 SelectionMove[nb,All,Notebook];
 Or@@Map["Evaluating"/.#&,Developer`CellInformation[nb]]
]

This is just a diagnostic message, when you're trying to redefine a kernel like "Test":

AddTestEvaluator::exists = "Evaluator `1` is already defined, but has a definition that is `2` and not the expected `3`.";

This is code to add an evaluator, like "Test" to the frontend:

AddTestEvaluator[evaluator_String] := Module[
 {evaluatornames, testevaluator},
 evaluatornames = EvaluatorNames /. Options[$FrontEnd, EvaluatorNames];
 testevaluator = evaluator -> {"AutoStartOnLaunch" -> False};
 Which[
  MemberQ[evaluatornames, evaluator -> {"AutoStartOnLaunch" -> False}],
  Null,
  MemberQ[evaluatornames, evaluator -> _],
  Message[AddTestEvaluator::exists,
  evaluator,
  evaluator /. (EvaluatorNames /. Options[$FrontEnd, EvaluatorNames]),
  {"AutoStartOnLaunch" -> False}
 ],
 True,
 AppendTo[evaluatornames, testevaluator];
 SetOptions[$FrontEnd, EvaluatorNames -> evaluatornames]
 ]
]

Finally, this is the code to evaluate a notebook under a "Test" kernel and save the evaluated kernel:

 UsingFrontEnd[     
  AddTestEvaluator["Test"];
  nb = NotebookOpen["test.nb"];
  SetOptions[nb,Evaluator->"Test"];
  SelectionMove[nb,All,Notebook];
  SelectionEvaluate[nb];
  NotebookPauseForEvaluation[nb];
  NotebookSave[nb]
 ]

I'm still looking into a solution for your full problem (having a defined in the local command
line kernel).

ぃ双果 2024-12-30 16:03:46

这是在 Windows 上,使用 Arnouds 做得很好,只添加普通的旧 MathLink (顺便说一句,相当慢......):

link = LinkCreate["8000", LinkProtocol -> "TCPIP"];
UsingFrontEnd[
NotebookPauseForEvaluation[nb_] := Module[{},
 While[ NotebookEvaluatingQ[nb], Pause[.25] ] ];
NotebookEvaluatingQ[nb_]:=Module[{},
 SelectionMove[nb,All,Notebook];
 Or@@Map["Evaluating"/.#&,Developer`CellInformation[nb]]
];
nb = NotebookOpen["G:\\mma\\test.nb"];
SelectionMove[nb, Before, Notebook];
NotebookWrite[nb, Cell["Link = LinkConnect[\"8000\", LinkProtocol -> \"TCPIP\"]", "Input"]];
SelectionMove[nb, After, Notebook];
NotebookWrite[nb, Cell["LinkWrite[Link, a]", "Input"]];
SelectionMove[nb, All, Notebook];
SelectionEvaluate[nb];
a = LinkRead[link];
Print["a = ",a];
]

This is on Windows, using Arnouds nice work and just adding plain old MathLink (pretty slow btw ...):

link = LinkCreate["8000", LinkProtocol -> "TCPIP"];
UsingFrontEnd[
NotebookPauseForEvaluation[nb_] := Module[{},
 While[ NotebookEvaluatingQ[nb], Pause[.25] ] ];
NotebookEvaluatingQ[nb_]:=Module[{},
 SelectionMove[nb,All,Notebook];
 Or@@Map["Evaluating"/.#&,Developer`CellInformation[nb]]
];
nb = NotebookOpen["G:\\mma\\test.nb"];
SelectionMove[nb, Before, Notebook];
NotebookWrite[nb, Cell["Link = LinkConnect[\"8000\", LinkProtocol -> \"TCPIP\"]", "Input"]];
SelectionMove[nb, After, Notebook];
NotebookWrite[nb, Cell["LinkWrite[Link, a]", "Input"]];
SelectionMove[nb, All, Notebook];
SelectionEvaluate[nb];
a = LinkRead[link];
Print["a = ",a];
]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文