C extension module doesn't throw exception after setting errorindicator through PyErr_SetString()

R

rahul

I am implementing a C extension module, during this I saw that when I set the global error indicator and error message through PyErr_SetString() API and return false.

But it doesn't throw any error when I tried to check the error through sys.exc_info() then it returns (NULL, NULL, NULL) tuple.

When I return NULL through the C extension module's function then it works correctly and throws the exception as expected.

The skeleton looks like:

static PyObject* check(PyObject* sef, PyObject* args)
{
PyObject* input = NULL;
if (!PyArg_ParseTuple(args, "O", &input)){
return NULL;
}
.....
.....
PyErr_SetString(PyExc_Exception, "Throwing Error through check function");
Py_RETURN_FALSE;
}

Any idea on why this is happening? Any help will be appreciated.

Thanks,
Rahul
 
T

Tim Golden

I am implementing a C extension module, during this I saw that when I
set the global error indicator and error message through
PyErr_SetString() API and return false.

But it doesn't throw any error when I tried to check the error
through sys.exc_info() then it returns (NULL, NULL, NULL) tuple.

When I return NULL through the C extension module's function then it
works correctly and throws the exception as expected.

The skeleton looks like:

static PyObject* check(PyObject* sef, PyObject* args) { PyObject*
input = NULL; if (!PyArg_ParseTuple(args, "O", &input)){ return
NULL; } ..... ..... PyErr_SetString(PyExc_Exception, "Throwing Error
through check function"); Py_RETURN_FALSE; }

Any idea on why this is happening? Any help will be appreciated.


Because you're returning False. You should be returning NULL. Which is
why it works when you do :)

Have a look at the first line of this page:

http://docs.python.org/py3k/extending/extending.html#intermezzo-errors-and-exceptions


Which piece of documentation led you to think that returning False was
the thing to do here? Perhaps there's a doc that needs fixing?


TJG
 
R

rahul

Hi TJG,

The above link also doesn't strictly said that return value should be NULL only, it only said that usually NULL pointer used. No where I saw that it is nessasory t

At http://docs.python.org/c-api/exceptions.html. it is written that "Most functions also return an error indicator, usually NULL if they are supposed to return a pointer, or -1 if they return an integer (exception: the PyArg_*() functions return 1 for success and 0 for failure)." this also told thatusually NULL is used but we can change the return error indicator to any value. As like PyArg_*() used 0 for error value.

Thanks,
Rahul
 
R

rahul

Hi TJG,

The above link also doesn't strictly said that return value should be NULL only, it only said that usually NULL pointer used. No where I saw that it is nessasory t

At http://docs.python.org/c-api/exceptions.html. it is written that "Most functions also return an error indicator, usually NULL if they are supposed to return a pointer, or -1 if they return an integer (exception: the PyArg_*() functions return 1 for success and 0 for failure)." this also told thatusually NULL is used but we can change the return error indicator to any value. As like PyArg_*() used 0 for error value.

Thanks,
Rahul
 
T

Tim Golden

Hi TJG,

The above link also doesn't strictly said that return value should be
NULL only, it only said that usually NULL pointer used. No where I
saw that it is nessasory t

At http://docs.python.org/c-api/exceptions.html. it is written that
"Most functions also return an error indicator, usually NULL if they
are supposed to return a pointer, or -1 if they return an integer
(exception: the PyArg_*() functions return 1 for success and 0 for
failure)." this also told that usually NULL is used but we can change
the return error indicator to any value. As like PyArg_*() used 0 for
error value.

The docs you quote are very slightly confusing because they're combining
the standard practice (return NULL), the uncommon alternative (return
-1) and a few special cases present in the core functions.

In short, any function you expose in an extension module will be
returning a PyObject* and should return NULL if it is setting or
cascading an exception.

I'm not convinced that the docs need altering here: this is the first
time I've come across anyone who was confused. But if you think some
different wording might help, feel free to propose something.

TJG
 
R

rahul

When I use same code base for Python 3.x, then behavior is different. In this when I return false then also it throws exception but only when any other statement get executed after this

like below code:
...
...
b = None
try:
a = testModule.check(None)
except:
b = sys.exc_info()
then code execution doesn't come to except block.
But when I add one statement after calling check function then code execution goes into except block.

...
...
b = None
try:
a = testModule.check(None)
print( a )
except:
b = sys.exc_info()
 
R

rahul

When I use same code base for Python 3.x, then behavior is different. In this when I return false then also it throws exception but only when any other statement get executed after this

like below code:
...
...
b = None
try:
a = testModule.check(None)
except:
b = sys.exc_info()
then code execution doesn't come to except block.
But when I add one statement after calling check function then code execution goes into except block.

...
...
b = None
try:
a = testModule.check(None)
print( a )
except:
b = sys.exc_info()
 
T

Tim Golden

When I use same code base for Python 3.x, then behavior is different. In this when I return false then also it throws exception but only when any other statement get executed after this

like below code:
...
...
b = None
try:
a = testModule.check(None)
except:
b = sys.exc_info()
then code execution doesn't come to except block.
But when I add one statement after calling check function then code execution goes into except block.

...
...
b = None
try:
a = testModule.check(None)
print( a )
except:
b = sys.exc_info()


Sounds like you're entering into undefined behaviour. If you set an
exception and don't return NULL, you're leaving Python's internals in an
inconsistent state. I don't know the internal code paths, but presumably
in one version it just ignored the exception state while in the other it
noticed it but in a different point in the code at which point it raised
the exception. Or something.

Long-and-short: return NULL from an extension module function once
you've raised (or are cascading) an exception condition. Anything else
is undefined unless you know *exactly* what you're doing.


TJG
 
S

Stefan Behnel

rahul, 02.08.2012 11:50:
When I use same code base for Python 3.x, then behavior is different.

You might want to take a look at Cython. It moves most of these "funny"
little details off your shoulders.

Stefan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top