Ipython cannot find gROOT

This is:
Python 2.6.4 (r264:75706, Nov 4 2011, 03:13:05) / "[GCC 4.4.3] on linux2"
IPython 0.10.2 – An enhanced Interactive Python.

In [1]: from ROOT import *
In [2]: gROOT

NameError Traceback (most recent call last)
/…/ in ()
NameError: name ‘gROOT’ is not defined

In [1]: import ROOT
In [2]: ROOT.gROOT
Out[2]: <ROOT.gROOTWrapper object at 0x9bf098c>
======================================================================[/code] Note: this is a DIFEERENT version of ipython (and python) than the one that was dying …


yes, I noticed that (I originally had 0.10 and 0.11, with which I didn’t see a crash).

How important is this? The issue with ipython is that it likes to setup context for the execution of the individual lines and so quite often the normal python interpreter rules don’t apply (ipython is a python program run on top of the python interpreter, it’s not an interpreter itself). If the execution context does not remain the same from one statement to the next, then the lazy lookup hook can not possibly work.

In particular, this hack in ipython’s fakemodule.py is the trouble: # Hard assignment of the object's __dict__. This is nasty but deliberate. fm.__dict__.clear() fm.__dict__.update(dct)
Now, in later ipython’s, the execution context is main (like in the python interpreter main, not the fake module main), which is why that works.

Note that I can solve this for gROOT specifically, but I don’t see a clear way for the general case of “from ROOT import *”. Presumably, this could be fixed by grabbing hold of the ipython command line loop object and modifying it, but that may cease working if ipython internals change.

I’ll have a look at that latter option, but can’t promise anything.



this works, but I’m not certain it’s a good idea (rather, I’m certain it’s not a good idea in general, as user code may have specialized user_global_ns; by default, however, it is pointing to user_ns, so hijacking it in the default case is fine as user_ns will carry the default behavior with user_global_ns picking up the new behavior):from IPython.core.interactiveshell import InteractiveShell import ROOT InteractiveShell._instance.user_global_ns = {} ROOT.SetRootLazyLookup(InteractiveShell._instance.user_global_ns) print gROOT
I could add the above code with a protection of IPYTHON and a check for the version for which it is necessary.

Let me know what you think.


Well, I’m just a trespasser here.

It seems to me that a whole bunch of “long-living” systems use ipython 0.10 and they are probably going to stay with us for some time (this includes SLC-6, for example).
The newest Ubuntu 12.04 LTS (“long term service”) uses ipython 0.12 (I cannot test it for the moment so I don’t know if the bug is there or not).
Newest systems will use ipython 0.13, of course.

That said, I don’t know how often it happens that a user code has a “specialized user_global_ns”, but if it is not so common and if you can protect your “brutal fix” with a “IPYTHON” version, then maybe it’s worth of adding (I assume this “brutal fix” works for anything imported, not just the “gROOT” which I used for “test purposes”).

Hi Wim,

Not sure how many adjustments espcially for IPython you are willing to make, but IPython can be instructed to add objects to the lists of builtins: ipython.org/ipython-doc/rel-0.13 … _trap.html

They changed their API a lot after 0.10.2 when they dropped python-2.5 and also at later times, so I am not sure how stable that part of the API was. It looks like they aim for a 1.X release ATM, so maybe the dust has settled some.

The other option would be to mention in some documentation that ROOT and ipython play nice when keeping things under the module’s namespace. In 4 years I have had practically no issues with that. Personally I have to say making sure that ipython and ROOT play nicely together in the future is important since right now ipython is really the most predicatable and user-friendly interactive ROOT prompt (at least until cling comes out of hiding).




not sure builtin_trap can help?

Anyway, after having wasted some more hours on this, I’m giving up. The lazy lookup works fine within the call, but somehow IPython keeps on resetting the dict. Not clear to me where that is happening, or why, let alone what can be done about, and then there’s the general instability of it all across releases.

I’ve ended up simply putting in a warning so that if “from ROOT import *” is done under IPython, a message pops up stating that that isn’t supported (although that’d probably be clear already given that it doesn’t work :slight_smile: ).

Maybe if IPython stabilizes in the future and stops adding hacks that make it deviate from normal python behavior, I’ll revisit this.


How important is the lazy lookup anyways? I’ve often wished for a non-lazy lookup in order to do import ROOT, then tab-complete to help find the right object/method. It seems like maybe the problem isn’t so much IPython itself, but the combination of IPython and the lazy lookup.

I wish they had by now removed the “from foo import *” syntax from python altogether. I never use it and I wouldn’t even consider it. I don’t even use “from foo import bar”.



given that ROOT can auto-load classes (not to mention auto-generate e.g. STL in the cling-world), “from ROOT import *” is rather ill-defined …

Making tab-completion (and dir() through dir) work is an independent matter. That could look e.g. in the class table of already known classes as well as the set of globals or even rootmap entries (leaving the actual loading out of the picture).



just to show it can be done (and awaiting feedback …), I’ve checked in rlcompletion of “ROOT.” for classes. Example:[code]>>> import ROOT

ROOT.THashList ROOT.THashTable ROOT.THashTableIter

Seems fine (speed-wise) on my box …