我正在尝试在ipython笔记本中对ROOT文件进行一些操作(这里的ROOT是CERN的带有python接口的ROOT数据分析程序)。 ROOT令人讨厌的功能之一是它经常将输出直接发送到stdout而不是将这样的输出作为字符串返回。为了让这个输出在ipython笔记本中出现,我写了一点cell_magic
:
这是我的小细胞魔法代码
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()
的输出转到stdout,并不会出现在单元格的结果中。但是使用这个单元格魔法输出确实出现在单元格结果中!太棒了!
但是,如果我将单元魔法代码放入模块中,那么它就不起作用了。例如,我将上面的代码放入ipythonRoot.py
并在笔记本中执行import ipythonRoot.py
。当我尝试运行上面的%%rootprint
单元格时,我收到一条错误消息,指出f
未定义。我尝试将exec
行更改为exec cell in globals()
,但这没有帮助。
有办法做到这一点吗?另外,有没有更好的方法来编写cell_magic
函数(例如,我应该返回输出而不是打印它)?在此先感谢您的帮助!
答案 0 :(得分:2)
所以我通过查看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
属性,其中包含笔记本名称空间等。这可以定期导入,并且工作正常。
答案 1 :(得分:0)
如果我理解正确,magic / alias / user命名空间是分开的。执行'import'不会干扰magic / alias命名空间。 这就是为什么有%load_ext魔术的原因,但你必须定义你的入口点。 [R magic的例子]。(https://github.com/ipython/ipython/blob/master/IPython/extensions/rmagic.py#L617)。
另外,我建议将capture magic视为捕获stdout / err而不使用临时文件。
一旦此方法有效,您还可以将扩展名添加到the extension index