[IPython-dev] Strange bug

Gregory Novak novak at ucolick.org
Fri Jan 5 13:30:50 CST 2007


I just spent the better part of a day trying to figure out what on
earth was going on with a rather strange bug.  The dramatis personae:

pyIDL is a bit of python + c code that allows you call IDL
(http://www.ittvis.com/idl/) code from Python
(http://www.its.caltech.edu/~mmckerns/software.html) 

(for Mike: IPython is an enhanced interactive python shell
http://ipython.scipy.org/moin/) 

pyIDL provides getattr/setattr functions to access variables in IDL so
that instead of typing idl_instance.get('x') you can type
idl_instance.x  

There's also a function called eval that evaluates IDL expressions,
like so:
idl_instance.eval('y=x')

When I called idl_instance.eval('y=x') under plain vanilla python, it
worked fine.  When I called the same thing under IPython, I got
strange errors coming from IDL:

% Attempt to call undefined procedure/function: 'EVAL'.
% Execution halted at: $MAIN$          

This error message is coming from IDL, because apparently the string
"eval(...)" is getting passed to the IDL instance rather than
executing the python idl_instance.eval function.

What on Earth is going on?  It works in Python, but not IPython, and
the failure mode is very strange... an extra string "escapes" into the
IDL instance.

Well, I spent a bunch of time fooling around with providing my own
__getattribute__, __setattribute__, etc functions that printed
messages in the idl_instance object, so that I could see how it was
treated differently in Python vs. IPython.  

It turns out that apparently IPython is calling 
idl_instance.__getattribute__('eval("y=x")).  Then the string
'eval("y=x")' is passed to pyIDL's __getattr__ method, which checks to
see if 'eval("y=x")' is an IDL variable.  Needless to say, it isn't,
and it triggers the above error message.

I'd love to provide a backtrace but when I run the code under pdb,
there's no problem (__getattribute__ is only called on strings like
'eval', not 'eval("y=x")').  And when I try to throw an exception in
the offending call to __getattribute__ in order to get a backtrace,
it's caught somewhere higher up, but I can't see where.  I've disabled
all of the try:/except: blocks whithin pyIDL, and none of them seem to
be catching it.  So it's either in C code or there's soemthing weirder
going on.

What's the point of all this?  Well, it definitely qualifies as a bug,
but there's an easy workaround: type idl_instance.eval("y = x").  The
spaces apparently prevent IPython from doing its strange
__getattribute__ call.  

That's all...
Greg


More information about the IPython-dev mailing list