Cedric Adjih adjih at
Tue May 2 00:49:51 CEST 2000

mdefreitas at wrote:
> In article <8ehnvs$m0h$1 at>,
>   Cedric Adjih <adjih at> wrote:
>> mdefreitas at wrote:
>> [...]
>>   Indeed.
>>   PyRun_File is actually implementing most of the "execfile(...)"
>> code (see
>> Python source code for execfile is also an example of use for
>> PyRun_File.
>>   Passing empty dictionaries would be a way to have a "clean"
>> environment except if a script imports a Python module and fiddles
>> with its internals. Because modules will be shared among scripts.
>> But fiddling with internals is very bad style.
>> -- Cedric

> Hmmm... I looked at the source code for execfile and it looks like it
> either passes PyRun_File the dictionaries that were passed into
> execfile itself, or if none was passed in, it passed PyRun_File the
> current dictionaries as default. I believe that what I need to do is
> pass in EMPTY dictionaries for the globals and locals. I tried the
> following:
> PyRun_File(fd, script, Py_file_input, PyDict_New(), PyDict_New());
> But that didn't seem to work. The top level script seemed OK, but the
> nested one didn't seem to execute. Is there something else that needs
> to be done? Is it bad to pass in an empty global dictionary? 

You're right, it's bad to pass an empty dictionnary as globals.
If you used PyErr_Print() and other functions, you'd have get
a nice traceback :-)
I guess Python tries to find builtins function from globals
(or at least __import__). Here is a better example:

------------- testpython.c

#include <assert.h>
#include <Python.h>

static PyObject* internal_pid(PyObject* self, PyObject* args)
{ return Py_BuildValue("i", getpid()); }

static PyMethodDef InternalMethods[] = {
  {"getPid",  internal_pid, METH_VARARGS},
  {NULL,      NULL}        /* Sentinel */

main(int argc, char**argv)
  FILE* f=fopen("", "r");
  PyObject* localDict;
  PyObject* result;
  PyObject* mainModule;
  PyObject* mainModuleDict;
  /* init*/
  /* get __main__ info */
  if(mainModule==NULL) { PyErr_Print();
    exit(EXIT_FAILURE); }
  if(mainModuleDict==NULL) { PyErr_Print(); exit(EXIT_FAILURE); }
  Py_InitModule("internal", InternalMethods);
  /* first run */
  result=PyRun_File(f, "", Py_file_input, 
      mainModuleDict, localDict);
  if(result!=NULL) {
  } else {
    /*<>, and
  /* second run */
  f=fopen("", "r");
  result=PyRun_File(f, "", Py_file_input, 
    mainModuleDict, localDict);
  if(result!=NULL) Py_DECREF(result);
  else PyErr_Print();
  /* free */

import string
import internal
print "-"*75
print "globals:",globals()
print "locals:", locals()
print  "dir():", dir()
def f(x):
  return x+1
print "ok", internal.getPid()
print "globals:",globals()
print "locals:", locals()
print  "dir():", dir()
Variables and functions (i.e. new definitions) are put into
the locals dictionnary, which is what you want.
>                                                              Also, I
> noticed that there was a PyDict_New function, but not a PyDict_Delete
> function... I assume memory cleanup is automatic?

Unfortunatly, no.
You have to use the Py_INCREF/Py_DECREF functions, as documented
If you are using C++, CXX will offer wrappers (and other goodies),
that'll maintain this automatically, but CXX uses templates and require
an up-to-date C++ compiler. 
SCXX is a lighter version of the same idea without templates 
(which is what I use).

-- Cedric

More information about the Python-list mailing list