[IPython-user] Problem with IPShellEmbed
mike at pcblokes.com
Wed Feb 2 06:25:49 CST 2005
Fernando Perez wrote:
> mike at pcblokes.com wrote:
>> Right... I'm afraid stack frames are still a deeply black art to me.
>> Perhaps a better solution would be to put IPython in a 'Psyco proof
>> bubble' ?
>> Surely IPython doesn't go deeper into the stack than the
>> function/scope that
>> *called* IPython. So long as the locals are available from this frame
>> we should
>> be alright ?
>> So if you can guarantee (by hook or by crook) that we can access that
>> frame ok
>> everything is fine ? I'm probably being naive of course.......
> The problem is that an ipython user can request information about a
> psyco-ized object, whose stack is unavailable.
> I had a look at the embedding calls, and it would be easy to change
> the code to avoid the _getframe() calls IF you call it with a
> locals/globals pair of dicts. In iplib.py, around line 1066, change
> the version I put up yesterday with this:
> # Get locals and globals from caller
> if local_ns is None or global_ns is None:
> call_frame = sys._getframe(stack_depth).f_back
> if local_ns is None:
> local_ns = call_frame.f_locals
> if global_ns is None:
> global_ns = call_frame.f_globals
> This will avoid the _getframe call IF you provide BOTH a locals and a
> globals dict. In this case, users will NOT be able to call the
> embedded instance with a simple
> since they will HAVE to give ipython something to go with as a
> namespace. So the call will have to be:
> or positionally:
> ipshell('header string',localdict,globaldict)
Hmmm... even with these changes I still die if
``ipshell(local_ns=localdict,global_ns=globaldict)`` is called.
I have made sure to call ``psyco.cannotcompile(interactive)`` so the
interactive function *shouldn't* be bound by psyco. I am explicitly
passing in locals() and globals() to the interactive function.
The error I get is as follows :
D:\Python Projects\modules in progress\movpy\files\test>movpy.py -i
IPython Interactive Shell. See the manual for a list of features and tips.
Ctrl-D to exit.
*** ITPL FATAL ERROR ***
Invalid frame in the stack, no globals/locals available.
Frame object: <psyco.support.PsycoFrame instance at 0x015E7828>
This message just cycles until I hit ctrl-D. In this case psyco.full()
is not called by my script but in ptest2.py which is compiled and
eval'd. My problem is that I have no way of knowing whether a script we
run will call psyco.full() - I just have to warn my users that if they
call scripts that have psyco they can't use IPython. In some ways this
situation is worse - at least before IPython actually bombed out (so I
could trap the error and do something else) !!
I have asked Armin Rigo for help on this - including *either* a way to
just apply psyco to the code object returned by compile (at the moment
psyco.bind(object) doesn't work with code objects) - *or* a way of
telling if psyco.full() has been called.
Note the following from the psyco user guide (which might or might not
be helpful) :
*Frame objects* are emulated. The sys._getframe function returns an
instance of a custom class which emulates the standard frame objects'
behavior as much as possible. The frames corresponding to a
Psyco-accelerated frame have some placeholder attributes, notably
f_locals. /There is no way to read the local variables of a
Psyco-accelerated frame./ Actually, only the f_code, f_globals, f_back
and f_lineno fields are well-tested. Also keep in mind that if you
obtain a real frame object (which you can do with some other mean than
sys._getframe, e.g. via a traceback object), the f_back chained list
will not include the Psyco-accelerated frames.
>> Psyco is a common tool, so it would be *better* if IPython could work
>> with it
>> (or at least around it). If there are any changes to psyco that would
>> help this
>> then I'm sure Armin would be willing to consider them.
> I agree, and I'd like to play nice with psyco. But I hope you realize
> that embedding a live interpreter into a function where psyco has
> explicitly destroyed the stack is not exactly easy :)
More information about the IPython-user