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

Discussion in 'Python' started by rahul, Aug 2, 2012.

  1. rahul

    rahul Guest

    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
     
    rahul, Aug 2, 2012
    #1
    1. Advertising

  2. rahul

    Tim Golden Guest

    On 02/08/2012 09:57, rahul wrote:
    > 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
     
    Tim Golden, Aug 2, 2012
    #2
    1. Advertising

  3. rahul

    rahul Guest

    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
     
    rahul, Aug 2, 2012
    #3
  4. rahul

    rahul Guest

    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
     
    rahul, Aug 2, 2012
    #4
  5. rahul

    Tim Golden Guest

    On 02/08/2012 10:21, rahul wrote:
    >
    > 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
     
    Tim Golden, Aug 2, 2012
    #5
  6. rahul

    rahul Guest

    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()


    On Thursday, 2 August 2012 15:07:08 UTC+5:30, Tim Golden wrote:
    > On 02/08/2012 10:21, rahul wrote:
    >
    > >

    >
    > > 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
     
    rahul, Aug 2, 2012
    #6
  7. rahul

    rahul Guest

    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()


    On Thursday, 2 August 2012 15:07:08 UTC+5:30, Tim Golden wrote:
    > On 02/08/2012 10:21, rahul wrote:
    >
    > >

    >
    > > 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
     
    rahul, Aug 2, 2012
    #7
  8. rahul

    Tim Golden Guest

    On 02/08/2012 10:50, rahul wrote:
    > 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
     
    Tim Golden, Aug 2, 2012
    #8
  9. 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
     
    Stefan Behnel, Aug 2, 2012
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kerri
    Replies:
    2
    Views:
    13,057
    Kevin Spencer
    Oct 27, 2003
  2. VisionSet
    Replies:
    51
    Views:
    4,316
    Tony Morris
    Jul 14, 2004
  3. Replies:
    15
    Views:
    7,625
    Roedy Green
    Sep 8, 2005
  4. David Eger

    PyErr_SetString() != raise ?

    David Eger, Jul 15, 2003, in forum: Python
    Replies:
    1
    Views:
    694
    Modular Forms Boy
    Jul 15, 2003
  5. Emanuele D'Arrigo

    To throw or to throw not?

    Emanuele D'Arrigo, Nov 14, 2008, in forum: Python
    Replies:
    6
    Views:
    338
    Emanuele D'Arrigo
    Nov 15, 2008
Loading...

Share This Page