【问题标题】:How to evaluate a notebook from the command line?如何从命令行评估笔记本?
【发布时间】:2011-12-28 14:43:53
【问题描述】:

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

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


这是我目前所拥有的:

首先,we need to start a headless X server 在远程 Linux 机器上,这样前端就可以在那里运行(并打开笔记本)。如果您在本地计算机上工作,请跳过此步骤。

Xvfb :1 &
export DISPLAY=:1

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

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

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

Out[1]= -NotebookObject-

在尝试评估笔记本后,显然我得到了dialog,我需要使用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

【问题讨论】:

  • 看起来我们的工作方式相似,而且同样懒惰!
  • +1 我也很想知道这个!我很想在我们的 HPC 上的远程系统上评估我的笔记本。

标签: wolfram-mathematica mathematica-frontend


【解决方案1】:

这是对您问题的部分回答。以下代码打开一个笔记本,为其分配一个 “测试”内核,评估该内核中的笔记本,等待评估完成并 保存评估的笔记本。它确实不会导致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 行内核)。

【讨论】:

  • 这已经很有用了!您是否知道是否有一种简单 方法可以在内核之间传输与符号关联的定义?这正是并行计算期间发生的事情,以及 DistributeDefinitions 所做的事情。所以我想这已经实现了。但是执行此操作的功能是否可供用户访问?
【解决方案2】:

这是在 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];
]

【讨论】:

  • 谢谢!我们真的需要LinkProtocol -> "TCPIP" 还是我们可以使用更有效的默认值? (我认为默认情况下它使用内存映射文件进行进程间通信)
  • 可能。至少我不能让它与 LinkProtocol -> "SharedMemory" 一起使用
  • 顺便说一句:你为​​什么真的需要这个?通过 DumpSave 或其他方式保存结果不是更容易吗?
  • 也许他在笔记本电脑上开发代码并希望在远程机器上运行它。这就是我所做的,我发现这些答案非常有用(在我的情况下,使用笔记本而不是 m 文件,所以我可以混合代码和排版讨论)。
猜你喜欢
  • 1970-01-01
  • 2017-05-25
  • 1970-01-01
  • 1970-01-01
  • 2016-08-22
  • 1970-01-01
  • 1970-01-01
  • 2021-06-07
  • 1970-01-01
相关资源
最近更新 更多