3

So - the good folks in the ROOT community made the following magic:

# This is for intercepting the output of ROOT
# In a cell, put %%rootprint so that the output that would normally be
# sent directly to the stdout will instead be displayed in the cell.
# It must be the first element in the cell.
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
            exec cell in self.shell.user_ns
            ROOT.gROOT.ProcessLine("gSystem->RedirectOutput(0);")
            print tmpFile.read()

# Register
ip = get_ipython()
ip.register_magics(RootMagics)

This works great if I do ye olde import rootprint in a cell in my IPython notebook - no complaints and it all works as expected. But, now I want to import this and do some stuff in a python file in ~/.ipython/profile/startup - python files in that directory apparently get run first thing when IPython starts, allowing access to whatever you defined therein. If I just do something simple (that does not import rootprint), everything works exactly as expected - I can make a function in the startup script and use it later at will. But when I try to import rootprint in the startup script and then start IPython (just IPython, not the notebook for now), it flips out with the complaint:

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/usr/lib/python2.6/site-packages/ipython-1.1.0-py2.6.egg/IPython/utils/py3compat.pyc in execfile(fname, *where)
    202             else:
    203                 filename = fname
--> 204             __builtin__.execfile(filename, *where)

/home/wjmills/.ipython/profile_nbserver/startup/dummy.py in <module>()
      2 import ROOT
      3 from ROOT import gROOT, TCanvas, TF1, TFile, TTree, gRandom, TH1F
----> 4 import numpy, rootprint
      5 
      6 def foo():

/home/wjmills/.ipython/profile_nbserver/startup/rootprint.py in <module>()
     31 
     32 # Register
---> 33 ip = get_ipython()
     34 ip.register_magics(RootMagics)

NameError: name 'get_ipython' is not defined

What happens to get_ipython in the context of a python script run on startup from profile/startup? Again, this all works perfectly if I do it interactively from an IPython notebook, so it seems to be something extra-special about the startup procedure. Thanks in advance!

Bill Mills
  • 411
  • 6
  • 16

2 Answers2

5

This is an incomplete suggestion -- but if get_ipython isn't in the namespace yet, you can try importing it directly:

from IPython import get_ipython
ipython_shell = get_ipython()

Also, ipython has different behavior when importing .py files vs .ipy files. You might try saving rootprint as an .ipy file.

I am not sure i would classify that as a solution if it works, but it may point you in the right direction.

Joshua M.
  • 109
  • 1
  • 4
0

I think the preferred way to register your magics is

def load_ipython_extension(ip):
    """Load the extension in IPython."""
    ip.register_magics(RootMagics)
zxxc
  • 355
  • 3
  • 12