无法访问ipython cell_magic中的笔记本变量

无法访问ipython cell_magic中的笔记本变量,ipython,ipython-notebook,Ipython,Ipython Notebook,我正在尝试对ipython笔记本中的根文件进行一些操作(这里的ROOT是CERN的根数据分析程序,带有python接口)。ROOT的一个恼人的特性是它经常直接将输出发送到stdout,而不是以字符串的形式返回这样的输出。为了让这个输出结果出现在ipython笔记本上,我写了一点cell_magic: 告诉ROOT用户将标准输出重定向到文件 在单元格中运行python命令 关闭根目录的输出重定向 读取文件并打印内容 这是我的小手机密码 import tempfile import ROOT f

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

  • 告诉ROOT用户将标准输出重定向到文件
  • 在单元格中运行python命令
  • 关闭根目录的输出重定向
  • 读取文件并打印内容
这是我的小手机密码

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.py
并在笔记本中导入ipythonRoot.py。当我尝试运行上面的
%%rootprint
单元格时,我得到一个错误,表示未定义
f
。我尝试将globals()中的
exec
行更改为
exec单元格,但没有效果


有办法做到这一点吗?另外,是否有更好的方法编写
cell\u magic
函数(例如,我是否应该返回输出而不是打印输出)?提前感谢您的帮助

如果我理解正确,magic/alias/user名称空间是分开的。执行“导入”不会干扰magic/alias命名空间。 这就是为什么会有%load\u ext魔法的原因,但是您必须定义您的入口点。[使用R magic的示例]。()

此外,我还建议您在不使用临时文件的情况下捕获stdout/err


一旦成功,您还可以将扩展添加到

,因此我通过查看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
属性,其中包含笔记本的名称空间。这可以定期导入,而且效果很好

谢谢你的好提示!Root的一个问题是它自己处理stdout/err,所以我认为没有办法告诉它重定向到一个文件。请注意,有一个快捷方式——如果您使用IPython实例(作为
shell
传递到
\uu init\ucode>),您可以调用
shell.ex(cell)
来执行代码。