2013-02-22 58 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