Providing full interaction with the run time

Dale Strickland-Clark dale at riverhall.nospam.co.uk
Sun Oct 29 11:53:35 CET 2006


We have a system we're developing which runs as a server. It has an xml-rpc
interface which I've extended to provide some debugging facilities. This
has already proved very useful and will continue to be so as the system is
prepared for live deployment.

The debugging interface attempts to emulate the Python interactive shell.
You type expressions, you get an answer. You type statements, they get
executed.

The problem is these two types of input are handled differently by Python.
You don't seem to be able to pass statements (which includes assignments)
and expressions through the same calls.

There are three keywords that support this type of function: EXEC, EVAL and
COMPILE. We can ignore EXEC for this because it doesn't support saving and
restoring a local environment and EVAL can do it better.

When you COMPILE code for EVAL, you have to say what sort of statement it
is. You can't pass an assignment as an expression:

>>> lcls={}
>>> r = eval(compile('a=1', '<>', 'eval'), globals(), lcls)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<>", line 1
    a=1
     ^
SyntaxError: invalid syntax

However, changing option 'eval' to 'single' is OK for statements:

>>> lcls={}
>>> r = eval(compile('a=1', '<>', 'single'), globals(), lcls)
>>> lcls
{'a': 1}
>>> 

But if I use 'single', I can't get expression results because the stupid
function prints them on the console.

>>> r = eval(compile('a', '<>', 'single'), globals(), lcls)
1
>>> print r
None

I can use the 'eval' option but that doesn't take assignments, remember?

>>> r = eval(compile('a', '<>', 'eval'), globals(), lcls)
>>> print r
1

The compile function also supports an 'exec' parameter in place of 'eval' or
'single' but this throws away expression results so that's no help.

At the moment, I'm making a crude attempt to distinguish between statements
and expressions but it's easily fooled.

So the question is: how does my debug interface (which operates over RPC)
decide which type of COMPILE it wants?

Or am I going about this all wrong?

(I don't need warnings about the obvious security implications of this
interface.)

Thanks
-- 
Dale Strickland-Clark
Riverhall Systems - www.riverhall.co.uk




More information about the Python-list mailing list