THE answer?

mdefreitas at sikorsky.com mdefreitas at sikorsky.com
Thu May 4 04:49:25 CEST 2000


> I think we need to send PyRun_File a COPY of the global
> dictionary, no? If so, how do we create a copy of a dictionary.
> I couldn't find anything like that in C/API document..

OK, forget that... I think I have the real answer here... rather than
copy the global dictionary, I'll just create one with the necessary
elements for each recursive call. This is the final answer which seems
to work:

void interp(char *file) {
   static int nest_level = 0;
   FILE *fd = fopen(file, "r");
   if (nest_level == 0) Py_Initialize();
   nest_level++;
   PyObject *dict = PyDict_New();
   PyDict_SetItemString(dict, "__builtins__",
      PyEval_GetBuiltins());
   PyRun_String("import ui\n"); // get my extension
   PyRun_File(fd, file, Py_input_file, dict, dict);
   if (Py_FlushLine()) PyErr_Clear();  // flush output
   nest_level--;
   if (nest_level == 0) Py_Finalize();
}

This works, and each recursive call to the interpreter has a fresh set
of global vars. You will note the lack of error checking and memory
cleanup. Here is my more complicated version... Is my error checking OK?

int interp(char *script) {
   static int  nest_level = 0;
   static bool failed     = false;
   static boo  py_init    = false;

   nest_level++;
   FILE *fd;
   if (!(fd = fopen(script, "r"))) {
      failed = true;
      cerr << "interp: Cannot open script " << script << endl;
      if (py_init) PyErr_BadArgument();
   } else {
      if (nest_level == 1) {
         Py_Initialize();
         py_init = true;
      }
      PyObject *dict = PyDict_New();
      if (!dict) {
         failed = true;
         PyErr_Print();
      } else {
         PyDict_SetItemString(dict, "__builtins__",
            PyEval_GetBuiltins());
         PyObject *stat1 = PyRun_String("import spear\n", Py_file_input,
            dict, dict); // import my extensions
         if (!stat1) {
            failed = true;
            PyErr_Print();
         } else {
            Py_DECREF(stat1);
            PyObject *stat2 = PyRun_File(fd, script, Py_file_input,
               dict, dict);
            if (!stat2) {
               failed = true;
               PyErr_Print();
            } else {
               Py_DECREF(stat2);
               if (Py_FlushLine()) PyErr_Clear(); // flush output
            }
         }
         Py_DECREF(dict);
      }
   }
   nest_level--;

   int ret_val = (failed ? -1 : 0);
   if (nest_level == 0) {
      if (py_init) {
         py_init = false;
         if (failed) PyErr_Clear();
         Py_Finalize();
      }
      failed = false;
   }

   return(ret_val);
}

I hope my memory cleanup is OK. I'll worry about passing args as locals
later. Thanks for everyone's help... especially Cedric Adjih and Warren
Postma (via email).




Sent via Deja.com http://www.deja.com/
Before you buy.



More information about the Python-list mailing list