better way of executing expression/statement in C?

Discussion in 'Python' started by David Faden, May 20, 2004.

  1. David Faden

    David Faden Guest

    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
    David Faden, May 20, 2004
    #1
    1. Advertising

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

    [rlratzel@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
    >
    >
    Rick L. Ratzel, May 21, 2004
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. MrTrix
    Replies:
    8
    Views:
    725
    Roy Johnson
    Oct 6, 2003
  2. Paul Rubin
    Replies:
    5
    Views:
    416
    Hendrik van Rooyen
    Aug 6, 2009
  3. Replies:
    0
    Views:
    190
  4. Replies:
    11
    Views:
    230
    Dr.Ruud
    May 22, 2007
  5. Replies:
    2
    Views:
    52
    Mark H Harris
    May 13, 2014
Loading...

Share This Page