Adding extra frames to traceback in C module

greg greg at cosc.canterbury.ac.nz
Sat Jun 10 11:25:54 CEST 2006


Roger Binns wrote:
> One thing I would like to do in my extension module is
> add extra frames to the traceback when an extension
> occurs.
>
> I did find snippets of code
> doing things like PyTraceback_Here but they use a real
> Python frame which I don't have and don't know how to
> synthesize.

This is the code Pyrex uses to add frames to the traceback.
It creates a fake frame object and fills in just enough
of it to keep the traceback printing code happy.

Or you could just use Pyrex for your extension module
in the first place, and get it done for you automatically.

-----------------------------------------------------------
#include "compile.h"
#include "frameobject.h"
#include "traceback.h"

static void __Pyx_AddTraceback(char *funcname) {
   PyObject *py_srcfile = 0;
   PyObject *py_funcname = 0;
   PyObject *py_globals = 0;
   PyObject *empty_tuple = 0;
   PyObject *empty_string = 0;
   PyCodeObject *py_code = 0;
   PyFrameObject *py_frame = 0;

   py_srcfile = PyString_FromString(%(FILENAME)s);
   if (!py_srcfile) goto bad;
   py_funcname = PyString_FromString(funcname);
   if (!py_funcname) goto bad;
   py_globals = PyModule_GetDict(%(GLOBALS)s);
   if (!py_globals) goto bad;
   empty_tuple = PyTuple_New(0);
   if (!empty_tuple) goto bad;
   empty_string = PyString_FromString("");
   if (!empty_string) goto bad;
   py_code = PyCode_New(
     0,            /*int argcount,*/
     0,            /*int nlocals,*/
     0,            /*int stacksize,*/
     0,            /*int flags,*/
     empty_string, /*PyObject *code,*/
     empty_tuple,  /*PyObject *consts,*/
     empty_tuple,  /*PyObject *names,*/
     empty_tuple,  /*PyObject *varnames,*/
     empty_tuple,  /*PyObject *freevars,*/
     empty_tuple,  /*PyObject *cellvars,*/
     py_srcfile,   /*PyObject *filename,*/
     py_funcname,  /*PyObject *name,*/
     %(LINENO)s,   /*int firstlineno,*/
     empty_string  /*PyObject *lnotab*/
   );
   if (!py_code) goto bad;
   py_frame = PyFrame_New(
     PyThreadState_Get(), /*PyThreadState *tstate,*/
     py_code,             /*PyCodeObject *code,*/
     py_globals,          /*PyObject *globals,*/
     0                    /*PyObject *locals*/
   );
   if (!py_frame) goto bad;
   py_frame->f_lineno = %(LINENO)s;
   PyTraceBack_Here(py_frame);
bad:
   Py_XDECREF(py_srcfile);
   Py_XDECREF(py_funcname);
   Py_XDECREF(empty_tuple);
   Py_XDECREF(empty_string);
   Py_XDECREF(py_code);
   Py_XDECREF(py_frame);
}

--
Greg



More information about the Python-list mailing list