2013-02-22 71 views
1

我想在ipython笔记本上做一些ROOT文件的操作(ROOT这里是CERN的ROOT数据分析程序和python界面)。 ROOT的烦人特性之一是它经常直接向stdout发送输出,而不是像字符串那样返回这样的输出。为了让这个输出出现在IPython的笔记本于是,我写了一个小cell_magic说:不能访问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函数(例如,我应该返回输出而不是打印它)?预先感谢任何帮助!

回答

0

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

另外我会建议寻找capture magic捕获stdout/err没有临时文件。

一旦这个工作,你也可以添加扩展你the extension index

+0

感谢您的好提示! Root的一个问题是它自己处理stdout/err,所以我不认为有办法让它重定向到一个文件。 – Adam 2013-02-23 14:39:43

2

所以我想通了这一点通过查看IPython的代码,具体的IPython /核心/魔法/ 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属性。这可以定期导入,它工作正常。

+0

请注意,有一个快捷方式 - 如果您使用IPython实例(传递给'__init__'作为'shell'),则可以调用'shell.ex(cell)'来执行代码。 – 2013-02-23 15:55:36