3

我正在尝试对 ipython 笔记本中的 ROOT 文件进行一些操作(这里的 ROOT 是 CERN 的带有 python 接口的 ROOT 数据分析程序)。ROOT 令人讨厌的特性之一是它经常将输出直接发送到标准输出,而不是将这样的输出作为字符串返回。为了让这个输出出现在 ipython 笔记本中,我写了一点cell_magic

  • 告诉 ROOT 将标准输出重定向到文件
  • 在单元格中运行 python 命令
  • 关闭 ROOT 的输出重定向
  • 读取文件并打印内容

这是我的小细胞魔法密码

import tempfile
import ROOT
from IPython.core.magic import register_cell_magic

@register_cell_magic
def rootprint(line, cell):
  """Capture Root stdout output and print in ipython notebook."""

  with tempfile.NamedTemporaryFile() as tmpFile:

    ROOT.gSystem.RedirectOutput(tmpFile.name, "w")
    exec cell
    ROOT.gROOT.ProcessLine("gSystem->RedirectOutput(0);")
    print tmpFile.read()

如果我将此代码放入 ipython 笔记本单元格并执行它,那么效果很好。例如,

In [53]: f = ROOT.TFile('myRootFile.root')   # Load the Root file


In [54]: %%rootprint
         f.ls()  # Show the contents of the ROOT file

         ... f.ls() output appears here - yay! ...

通常,输出f.ls()到标准输出并且不会作为单元格的结果出现。但是有了这个单元格魔法,输出确实出现在单元格结果中!这很棒!

但是,如果我将单元格魔术代码放入模块中,则它不起作用。例如,我将上面的代码放入ipythonRoot.pyimport ipythonRoot.py在笔记本中执行。当我尝试运行%%rootprint上面的单元格时,我收到一条错误消息,指出f未定义。我尝试将exec线路更改为exec cell in globals()但没有帮助。

有没有办法做到这一点?另外,有没有更好的方法来编写cell_magic函数(例如我应该返回输出而不是打印它)?提前感谢您的帮助!

4

2 回答 2

5

所以我通过查看 IPython 代码发现了这一点,特别是 IPython/core/magics/execution.py 有一些很好的提示。这是我的新模块

import tempfile
import ROOT
from IPython.core.magic import (Magics, magics_class, cell_magic)

@magics_class
class RootMagics(Magics):
  """Magics related to Root.

      %%rootprint  - Capture Root stdout output and show in result cell
  """

    def __init__(self, shell):
      super(RootMagics, self).__init__(shell)

  @cell_magic
  def rootprint(self, line, cell):
    """Capture Root stdout output and print in ipython notebook."""

    with tempfile.NamedTemporaryFile() as tmpFile:

      ROOT.gSystem.RedirectOutput(tmpFile.name, "w")
      ns = {}
      exec cell in self.shell.user_ns, ns
      ROOT.gROOT.ProcessLine("gSystem->RedirectOutput(0);")
      print tmpFile.read()

# Register
ip = get_ipython() 
ip.register_magics(RootMagics)

请注意Magics类的使用和shell包含笔记本名称空间等内容的属性。这可以定期导入并且工作正常。

于 2013-02-23T14:37:51.373 回答
1

如果我理解正确,magic/alias/user 命名空间是分开的。执行“导入”不会干扰魔术/别名命名空间。这就是为什么有 %load_ext 魔法的原因,但是你必须定义你的入口点。[R 魔法示例]。(https://github.com/ipython/ipython/blob/master/IPython/extensions/rmagic.py#L617)。

另外,我建议将其视为捕获魔术,它可以在没有临时文件的情况下捕获 stdout/err。

一旦这工作,您还可以将您的扩展添加到扩展索引

于 2013-02-23T10:03:34.410 回答