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