I try to move this to -dev as I hope there more people reading it who are competent in internal working :). So please replay to -dev only.
------------- The question is about use of generators in embedde v2.4 with asserts enabled. Can somebody explain, why the code in try2.c works with wrappers 2 and 3 but crashes on buggy exception for all others, that is pure generator and wrappers 1,4,5 ? In other words, what does [i in i for gen] do differently than other ways of iterating over gen, which helps it to avoid the assert, and also, how could I write something that is still a generator, but does not trigger the assert. While the right solution is to just fix python (which is done for v2.5) we need a workaround for the following reason We have added support for returning rows (as tuples and or dictionaries or classes) and sets of boths scalars and rows to PostgreSQL's pl/plpython embedded language, but have some objections to getting this into distribution, because there is a bug in python 2.4 doing a wrong assert and additional bug in how RedHat rpm build process which leaves the buggy asserts in python.so. So I hoped to write a simple wrapper class, but it only seems to work, when the generator is turned into list, which is not a good solution as it works directly against what generators are good for. -- ---------------- Hannu Krosing Database Architect Skype Technologies OÜ Akadeemia tee 21 F, Tallinn, 12618, Estonia Skype me: callto:hkrosing Get Skype for free: http://www.skype.com
#include <Python.h> #include <frameobject.h> const char *py_source = "def fn():\n" " print 'one'\n" " yield 1\n" " print 'two'\n" " yield 2\n" ; const char *wrapper_source1 = "class gwrap:\n" " def __init__(self,gen):\n" " self.gen = gen\n" " def __iter__(self):\n" " return iter(self.gen)\n" ; const char *wrapper_source2 = "def gwrap(gen):\n" " return [i for i in gen]\n" ; const char *wrapper_source3 = "def gwrap(gen):\n" " return (x for x in [i for i in gen])\n" ; const char *wrapper_source4 = "class gwrap:\n" " def __init__(self,gen):\n" " list = [i for i in gen]\n" " self.gen = list.__iter__()\n" " def __iter__(self):\n" " return iter(self.gen)\n" ; const char *wrapper_source5 = "def gwrap(gen):\n" " return (i for i in gen)\n" ; int main (int argc, char *argv[]) { Py_Initialize(); PyObject *main_module = PyImport_AddModule("__main__"); PyObject *globals = PyObject_GetAttrString( main_module, "__dict__"); // insert function code into interpreter PyObject *code = PyRun_String(py_source, Py_file_input, globals, NULL); Py_DECREF(code); // insert wrapper class into interpreter PyObject *code2 = PyRun_String(wrapper_source5, Py_file_input, globals, NULL); Py_DECREF(code2); // compile call to the function code = Py_CompileString("gwrap(fn())", "<string>", Py_eval_input); // code = Py_CompileString("fn()", "<string>", Py_eval_input); // do call PyObject *gen = PyEval_EvalCode((PyCodeObject *)code, globals, NULL); gen = PyObject_GetIter((PyObject *)gen); // iterate result PyObject *item; while ((item = PyIter_Next(gen))) { printf("> %ld\n", PyInt_AsLong(item)); Py_DECREF(item); } Py_DECREF(gen); Py_DECREF(code); Py_DECREF(globals); Py_Finalize(); return 0; }
-- http://mail.python.org/mailman/listinfo/python-list