pythonpython-c-api

How do I properly use Python's C API and exceptions?


If I do something like:

 >>> x = int(1,2,3,4,5)

I immediately get a fatal error (one that would end program execution if it was in a pre-written script)

 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 TypeError: int() takes at most 2 arguments (5 given)

and x remains undefined:

 >>> x
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 NameError: name 'x' is not defined

How would I go about implementing that in Python's C API? I found some documentation for it, but I am not sure that I know how to use it correctly.

Here is what I have been trying:

  1. Print:

     if(something) {
         PyErr_SetString(PyExc_TypeError, "Oh no!");
         PyErr_Print();
     }
    

    This, unfortunately, only prints the exception and the program continues. Additionally,—if I understand it correctly—PyErr_Print() removes the exception from some sort of queue so Python thinks that it is handled. This is what it looks like:

     >>> import awesomemod
     >>> x = awesomemod.thing()
     TypeError: Oh no!
     >>> x # x is defined because the function returns None eventually
     >>> 
    
  2. PyErr_Occurred():

     if(something) {
         PyErr_SetString(PyExc_TypeError, "Oh no!");
         PyErr_Occurred();
     }
    

    Behavior:

     >>> import awesomemod
     >>> awesomemod.thing()
     >>>
     TypeError: Oh no!
     >>>
    

    So it does it kind of late...

  3. return PyErr_Occurred():

     if(something) {
         PyErr_SetString(PyExc_TypeError, "Oh no!");
         return PyErr_Occurred();
     }
    

    Behavior:

     >>> import awesomemod
     >>> awesomemod.thing()
     <type 'exceptions.TypeError'>
     >>>
     TypeError: Oh no!
    

    This one is just really weird.

What do I need to do to get the behavior of built-in functions?

Edit: I tried what @user2864740 suggested in a comment and it worked perfectly!

 if(something) {
     PyErr_SetString(PyExc_TypeError, "Oh no!");
     return (PyObject *) NULL;
 }

Solution

  • Raising an exception in C is done by setting the exception object or string and then returning NULL from the function.