From: arcege at shore.net (Michael P. Reilly)
Date: Wed, 28 Apr 1999 19:28:42 GMT
Subject: running application config files written in Python
References: <m33e1lcvm7.fsf@froydnj.laptop.rose-hulman.edu>
Message-ID: <KjJV2.150$pX2.88806@news.shore.net>
Content-Length: 2668
X-UID: 950                                                  

Nathan Froyd <nathan.froyd at rose-hulman.edu> wrote:
: Say I have an application whose configuration language I want to be
: Python. I have all my extra types implemented in C. Now what I'm
: wondering is what's the best way to run that file so that the
: functions, variables, etc. get imported into the Python interpreter
: embedded in my program?

: Along the same lines, once I have run the file, what's the easiest way 
: to find out if a particular function/variable has been defined? For
: example, if I always wanted to run the user-defined function
: `startup_func', how would I go about doing that?

You can do this in two ways easily (and other ways less easily).

1)  Store the configuration files as modules, then import them.
If you are worried about security, you can import them using rexec.

    char modulename[] = "app_config";
    PyObject *config_module, *config_dict;
    PyObject *startup_func, *result;
    Py_Initialize();

    if ((config_module = PyImport_ImportModule(modulename)) != NULL &&
        (config_dict = PyModule_GetDict(config_module)) != NULL) {
      startup_func = PyDict_GetItemString(config_dict, "startup_func");
      /* look for startup function, but ignore if not present */
      result = NULL;
      if (startup_func != NULL && PyCallable_Check(startup_func))
        result = PyObject_CallFunction(startup_func, "");
      if ((startup_func == NULL || result == NULL) &&
          PyErr_Occurred() &&
          !PyErr_ExceptionMatches(PyExc_AttributeError))
        /* ignore AttributeError exceptions */
        PyErr_Print();
      PyErr_Clear();
      Py_XDECREF(startup_func);
      Py_XDECREF(result);
    } else {
      /* the module could not be loaded */
      PyErr_Print();
      Py_Exit(1);
    }

All values are stored in the module (accessed thru config_dict).  The
exception handling is more verbose then the next method.

2) Run the equivalent of execfile().

    char filename[] = "app_config.py";
    FILE *app_config;

    Py_Initialize();

    app_config = fopen(filename, "r");
    if (PyRun_Simplefile(app_config, filename) == -1) {
      fclose(app_config);
      /* the traceback has already been written to stderr */
      Py_Exit(1);
    }
    fclose(app_config);
    PyRun_SimpleString("try: startup_func()\n\
  except NameError: pass\n");

All values are stored in the current namespace (the module __main__,
and accessed thru the undocumented function PyEval_GetGlobals() or thru
other PyRun_* calls).  If there are exceptions raised, PyRun_* calls
handle the output; the return value is either -1 for failure, 0 for
success.

I would suggest using method (1).  Good luck.
  -Arcege





