[Pyrex] Handling exception when embedding

Franck Pommereau pommereau at univ-paris12.fr
Sat Nov 17 19:17:44 CET 2007


Dear all,

I'm trying to use Pyrex in order to embed Python modules into C
applications. I have problems to retrieve the information related to
exceptions from the C program (typically the name and message of the
exception).

Is there a standard way to do that?

Below is some stripped down code that causes an error (which is
unfortunately not the exact error I get with the module I really use,
but maybe if I can get a fix for this example, I'll be able to fix the
real code).

Let's say I have the following Python module:

# foo.py ###################################
import sys

class Foo :
    def __init__ (self, name) :
        self.name = name
    def hello (self) :
        print self.name, "says: hello", sys.argv[1]
        return 1
# end ######################################

I have the following Pyrex wrapper:

# cfoo.pyx #################################
cdef extern from "Python.h":
    void Py_Initialize()
    void Py_Finalize()
    void PySys_SetArgv(int argc, char **argv)

cdef extern void initcfoo()

cdef public void cfoo_initialize (int argc, char **argv) :
    Py_Initialize()
    PySys_SetArgv(argc, argv)
    initcfoo()

cdef public void cfoo_finalize () :
    Py_Finalize()

import sys

_error = ""

cdef public char *error () :
    global _error # in order to keep the Python str alive
    try :
        t, v, s = sys.exc_info()
        _error = ("%s: %s" % (str(t.__name__), str(v))).strip()
    except Exception, e : # see below why I need that
        _error = "*** %s: %s ***" % (e.__class__.__name__, str(e))
    return _error

import foo

cdef public object new_Foo (char *name) :
    return foo.Foo(name)

cdef public int Foo_hello (object self) :
    return self.hello()
# end ######################################

Then the following C program uses to module:

/* tester.c *******************************/
#include <Python.h>
#include "cfoo.h"

int main(int argc, char **argv) {
  PyObject *f;
  int i;
  cfoo_initialize(argc, argv);
  f = new_Foo("test");
  i = Foo_hello(f);
  if (i != 1) {
    printf("\n%s\n", error());
  }
  cfoo_finalize();
  return 0;
}
/* end *************************************/

When I compile and execute with no argument (so that sys.argv[1] does
not exist), I get the following message:

*** AttributeError: 'NoneType' object has no attribute '__name__' ***

Apparently sys.exc_info() returned (None, None, None).

On my real application (much more complex), the function error fails on
sys.exc_info() and I have the message:

*** NameError: sys ***

I discovered that I could work around by adding the line:

    sys = __import__("sys")

before to call sys.exc_info() but then, I still retrieve None as the
current exception...

I've also discovered that with functions that return nothing (void), my
function error works correctly.

I have no idea about what's going on. I should mention that I'm not a C
programmer and I could not really understand the code generated by Pyrex.

Any idea around?

Thanks in advance for help...
Franck





More information about the Pyrex mailing list