我正试图在ipython笔记本中对ROOT文件进行一些操作(这里的ROOT是CERN的ROOT数据分析程序,具有python接口)。 ROOT的一个令人讨厌的特征是它经常将输出直接发送到stdout而不是将此类输出作为字符串返回。 为了使此输出出现为ipython notebook中的结果,我编写了一个小的
如果我将这段代码放入一个 IPython 笔记本单元格并执行,那么它就可以很好地工作。例如:
cell_magic
,它:
- 告诉ROOT将stdout重定向到文件
- 运行单元格中的python命令
- 关闭ROOT的输出重定向
- 读取文件并打印内容
这是我的小的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! ...
< p >通常,f.ls()
的输出会送到stdout,而不会出现在单元格的结果中。但是使用这个单元格魔法,输出确实会出现在单元格结果中!太棒了!
但是,如果我将单元格魔法代码放入模块中,则无法正常工作。例如,我将上面的代码放入ipythonRoot.py
中,并在笔记本中执行import ipythonRoot.py
。当我尝试运行上面的%%rootprint
单元格时,会出现错误,指出f
未定义。我尝试将exec
行更改为exec cell in globals()
,但这并没有帮助。
有没有方法可以做到这一点?此外,是否有更好的编写cell_magic
函数的方法(例如,应该返回输出而不是打印输出)?非常感谢您的任何帮助!
__init__
),则可以调用shell.ex(cell)
来执行代码。 - Thomas K