我正在尝试对 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.py
并import ipythonRoot.py
在笔记本中执行。当我尝试运行%%rootprint
上面的单元格时,我收到一条错误消息,指出f
未定义。我尝试将exec
线路更改为exec cell in globals()
但没有帮助。
有没有办法做到这一点?另外,有没有更好的方法来编写cell_magic
函数(例如我应该返回输出而不是打印它)?提前感谢您的帮助!