1.2 Intermezzo: error and exception
Below is an important practice of the entire Python interpreter: When a function is an error, it should set an exception state and return an error value (usually a NULL pointer). An exception stores in a static global variable inside the interpreter; if this global variable value is null, the 'correlation value' of the second global variable storage exception (the second parameter) of the second global variable storage is indicated. The third variable is stored in the python code in the Python code, the stack is reversed tracking data. These three variables are python variables.exc_ type, sys.exc_value and sys.exc_traceback (see "Python Library Reference" SYS module section) corresponding to C variables. Understanding these variables is very important for understanding errors.
The Python API defines some types of functions to set exceptions.
The most important one is pyerr_setstring (). Its parameters are an exception object and a c-string. Abnormal objects are usually a predefined object like Pyexc_ZerodiVisionError. C String Indicates the cause of the error and converted to the Python string object stored in an exception 'correlation value' ('associated value').
Another useful function is pyerr_setfromerrno (), which only has an exception parameter and constructs the correlation value by checking global variable errno. The most commonly used function is pyerr_setObject (), which has two object parameters: exception and exception correlation value. You don't have to py_incref () objects to these functions.
You detect whether Non-DestructureLely detects whether the exception is set by the Pyerr_oCcurred () function. This function [1] returns the current exception object or returns NULL when there is no abnormality. General, because you can return the value of the value by the function, you don't have to call the pyerr_occurred () function to see if there is an error in a function call.
When the function f calls another function G, and detects that the functions of the following functions are errors, the function f should return an error value (usually null or -1). Function F should not call one of the PYER _ * () function - one of which has been called in G. F 's calihood must also return an error to inform it, nor does it need to call the pyer _ * () function, and the most detailed error message is reported by the first prior detected function. Once the error arrives at the primary loop of the Python interpreter, this will terminate the currently executed Python code and try to find the Python programmer specified by the exception handle.
(Under some conditions, the module can give the exact error message by calling the pyer _ * () function, and in this case, it is good. However, as a general rule, this is unnecessary, and will result in errors Information loss: Due to various reasons, most operations have failed.)
In order to ignore the abnormality generated by the failure of the function call, the abnormal condition must be cleared by clear calling functions pyerr_clear (). The pyerr_cle () function is called only if you want to pass the error to the interpreter. (It may be because there is something else, or there is no error occurred)
Each time you call Malloc () Failure must enter the direct caller of exception-malloc () must call pyerr_nomemory () and return the flag indicating its own errors. All object creation functions (such as pyint_fromlong () have been done, so this rule is only related to those who directly call malloc ().
Another point, Pyarg_Parsetuple () and similar function generated exceptions, functions with integer status return values believe that return value -1 means failure, 0 or integer is successful, just like UNIX system calls. Finally, when you return an error indication, carefully remove the garbage (by calling the PY_XDECREF () or PY_ DCREF () function you created).
What exception is generated is completely selected by yourself. There are some pre-declared C objects to process all built-in Python exceptions, such as Pyexc_ZerodivisionError: You can use it directly. Of course, you should choose an exception reasonably, don't use the Pyexc_TypeError indicate that the file cannot be opened (but should use pyexc_ioerror). If the parameter list has some errors, the function Pyarg_Parsetuple () usually generates a Pyexc_TypeError error. If you have a parameter must be within a specific range, or you must meet other conditions, you should use Pyexc_ValueError anomaly.
You can also define a unique new exception in your module. To do this, you should declare a static object variable on your file:
Static PyObject * spamerror;
And in the initialization function of your module (INITSPAM ()) initializes it (regardless of error check).
Pymodinit_func
INITSPAM (VOID)
{
PyObject * m;
M = py_initmodule ("spam", spammethods;
Spamerror = pyerr_newexception ("spam.rror", null, null;
PY_INCREF (spamerror);
Pymodule_addObject (M, "Error", spamerror);
}
Note: The unusual name in Python is spam.Error .. The pyerr_newexception () function can be derived from an exception base class (unless it is incoming another class rather than null), "Python Library Reference" has a built-in exception.
Please note:
Spamerror
Variables are maintained in newly created anomalies; this is deliberate! Since the exception can be deleted from the external code from the module, the owner of the class must confirm that the reference object is not released, resulting in
Spamerror
Become a wild pointer. Abnormal
C
Code is a kernel dump or other unpredictable consequences. Below, we will discuss this in this example.
Pymodinit_fun
As the return type of the function.
[1] Is the return value of this function?