better way of executing expression/statement in C?

Rick L. Ratzel rick.ratzel at scd.magma-da.com
Fri May 21 17:21:24 EDT 2004


    This might be slightly less kludgy...I tested it by implementing a 
crude input loop.  Here is the output:

[rlratzel at triumph ~/exp] ./pyexec
 >> a=3
RESULT: NULL
 >> b=4
RESULT: NULL
 >> a+b
RESULT: 7
 >> c=4
RESULT: NULL
 >> a+c
RESULT: 7
 >> import os
RESULT: NULL
 >> Done.

    Here is the code:

file: pyexec.c
--------
#include <Python.h>
#define INLEN 1024

/*
  * get string rep of a Python obj
  */
const char* getPyObjStringRepr( PyObject* pyObj ) {
   if( pyObj == NULL ) {
     return "NULL";
   } else {
     return PyString_AsString( PyObject_Str( pyObj ) );
   }
}


/*
  * print the results of evaluating Python expressions and statements
  */
int main( int argc, char** argv ) {

   PyObject* mainModObj;
   PyObject* mainDictObj;
   PyObject* returnObj;
   PyObject* resultObj;
   char userInput[INLEN];

   Py_Initialize();

   /*
    * create a different display hook to set a result var
    * rather than print to stdout and set __builtin__._
    */
   PyRun_SimpleString( "import sys, __main__" );
   PyRun_SimpleString( "def my_displayhook(o): __main__.__result=o" );
   PyRun_SimpleString( "sys.displayhook=my_displayhook" );

   /*
    * get the __main__ symbol table for evaluating within the top-most
    * scope and retrieving the result
    */
   mainModObj = PyImport_AddModule( "__main__" );
   if( mainModObj == NULL ) {
     return -1;
   }
   mainDictObj = PyModule_GetDict( mainModObj );

   /*
    * start an eval loop...only print 2 arrows since we are
    * not really trying to be Python
    */
   printf( ">> " );

   /*
    * start the loop
    */
   while( fgets( userInput, INLEN, stdin ) != NULL ) {

     /*
      * run a string from the command line like the interactive interp
      * does, handling both expressions and statements
      */
     returnObj = PyRun_String( userInput, Py_single_input,
			      mainDictObj, mainDictObj );

     if( returnObj == NULL ) {
       PyErr_Print();
       return -1;
     }

     /*
      * get the result as set by the displayhook and print it out
      */
     resultObj = PyDict_GetItemString( mainDictObj, "__result" );

     printf( "RESULT: %s\n", getPyObjStringRepr( resultObj ) );

     Py_DECREF( returnObj );
     if( Py_FlushLine() ) {
       PyErr_Clear();
     }

     /*
      * if a result was set, delete it so statements which dont return
      * a value dont return a prior set value
      */
     if( resultObj != NULL ) {
       PyRun_SimpleString( "del __main__.__result" );
     }

     printf( ">> " );
   }

   printf( "Done.\n" );
   return 0;
}
--------

    Not sure if that is exactly what you were looking for, but it does 
allow one to execute statements and expressions and process the result 
(if any).

-Rick Ratzel


David Faden wrote:
> Hi,
> 
> Given arbitrary Python source code input by the user, I want to get the 
> result of executing that source as an expression if it is an expression 
> and otherwise execute the source as a statement. Currently, I'm 
> accomplishing this as follows (in a category on NSString), but it seems 
> kludgy to rely on detecting a syntax error.
> 
> - (PyObject*)executePythonSourceWithGlobals:(PyObject*)globals
> {
>     const char* source = [self UTF8String];
>     PyObject* result = PyRun_String(source, Py_eval_input, globals, 
> globals);
>     if (!result && PyErr_ExceptionMatches(PyExc_SyntaxError)) {
>         PyErr_Clear();
>         result = PyRun_String(source, Py_file_input, globals, globals);
>     }
>     return result;
> }
> 
> How would you accomplish this? How does the interpreter do it?
> 
> Thank you.
> 
> David
> AIM: pitulx
> 
> 



More information about the Python-list mailing list