Embedding Question

Michael P. Reilly arcege at shore.net
Fri Jun 25 14:44:46 CEST 1999


Lloyd Weehuizen <tuna at delirious.fsnnet> wrote:
: On Thu, 24 Jun 1999 14:40:37 GMT, Michael P. Reilly <arcege at shore.net> wrote:
:>Lloyd Weehuizen <tuna at delirious.fsnnet> wrote:
:>: Hi
:>
:>: If I use the PyRun_String method, with a string that defines a method called

:>You can use any number of the "del" based operations.  But from the
:>high-level (using the PyRun_* functions), you would want:

: Ok, that would work, but I don't really know what functions are being
: defined, as the user can edit them. Is there no way to flush everything and
: start with a clean slate except doing a Finalize() and Initialize()?

: Hmm I spose I could search through the strings looking for all the "def"
: keyworks ;)

: Also, with the PyRun_String method, what is the difference between the
: locals and globals definition? I've set them to be the same, like the
: PyRun_SimpleString method does, could this be causing the problem? Are
: globals remembered the entire time the interpreter is running and locals
: only for that PyRun_String method? Into what namespace do "def" statements
: get loaded? Globals or locals? 

You can do a number of things.  But I would suggest creating a
new module and running the user code there, this is essentially the
purpose of the globals and locals values.

  PyObject *
  New_Python_Module()
    { static int modulenumber = 0;
      char name[50];

      sprintf(name, "run%d", modulenumber++);
      return PyModule_New(name);
    }
  /* if module is NULL, then create a new module to run the commands in
   * this allows multiple calls within the same module
   */
  PyObject *
  call_Python_string(pycmd, module)
    char *pycmd;
    PyObject **module;
    { PyObject *result = NULL;
      PyObject *globals;

      if (*module == NULL)
        *module = New_Python_Module();
      globals = PyModule_GetDict(*module);
      result = PyRun_String(pycmd, 0, globals, globals);
      return result;
    }

Notice that I did indeed keep the locals and globals the same.  Having
the locals is for evaluation within a function or class (or other such
"inner" namespace, cf. "Code blocks, execution frames, and namespaces"
in the Python Reference Manual).

Now to clean up, you dereference the module created:

  /* run two files in the same module, return 1 if successful, 0 otherwise
   * the module (and data) is destroyed.
   */
  int runfiles(file1, file2)
    char *file1, *file2;
    { int rc = 0;
      char *file_contents;
      PyObject *module = NULL;
      PyObject *result;

      file_contents = read_file(file1);
      result = call_Python_string(file_contents, &module);
      /* module should now not be NULL, unless the module could not
         be created */
      if (module == NULL || result == NULL) {
        Py_XDECREF(module);  /* destroy the module */
        Py_XDECREF(result);  /* destroy the object */
        return 0;
      }
      Py_DECREF(result);  /* python returns an object, so destroy it now */
      /* now run the next file, but in the same module */
      result = call_Python_string(file_contents, &module);
      Py_XDECREF(module); /* destroy the module */
      rc = (result != NULL);
      Py_XDECREF(result);
      return rc;
    }

Unless the user code modifies other modules (which it might), then this
is pretty good.  If you want to prevent even this security hole, then
look at the rexec module.

Alternatively, you can do the same that is done in some Python code:
  exec command in global_dicts

  int run_command(char *pycmd)
    { PyObject *result, *globals;
      PyObject *builtins;

      globals = PyDict_New();
      builtins = PyImport_ImportModule("__builtin__");
      PyDict_SetItemString(globals, "__builtins__", builtins);

      result = PyRun_String(pycmd, 0, globals, globals);
      Py_DECREF(globals);
      if (result == NULL)
        return 0;
      Py_DECREF(result);
      return 1;
    }

This is simpler, but sometimes you just need a module. :)

  -Arcege





More information about the Python-list mailing list