Extending and Embedding the Python Interpreter(二)

An important convention throughout the Python interpreter is the following: when a function fails, it should set an exception condition and return an error value (usually a NULL pointer). Exceptions are stored in a static global variable inside the interpreter; if this variable is NULL no exception has occurred. A second global variable stores the ``associated value'' of the exception (the second argument to raise). A third variable contains the stack traceback in case the error originated in Python code. These three variables are the C equivalents of the Python variables sys.exc_type, sys.exc_value and sys.exc_traceback (see the section on module sys in the Python Library Reference). It is important to know about them to understand how errors are passed around.

在python解释器里有很重要的一点是当一个函数发生错误时,它需要发出异常信息并且返回一个错误值。异常被存储在解释器的一个静态全局变量中,如果这个变量为NULL,那么就代表没有异常发生。第二个全局变量存储了与异常相关的信息。第三个变量存储了堆栈中的关于异常在源代码中的信息。这三个变量等效与python中的sys.exc_type, sys.exc_value and sys.exc_traceback 三个变量。

The Python API defines a number of functions to set various types of exceptions.

python api定义了一些设置异常类别的函数

The most common one is PyErr_SetString(). Its arguments are an exception object and a C string. The exception object is usually a predefined object like PyExc_ZeroDivisionError. The C string indicates the cause of the error and is converted to a Python string object and stored as the ``associated value'' of the exception.

PyErr_SetString()函数有两个参数,一个是异常对象,一个是C的字符串。此处的异常对象通常是预设的,而字符串用来说明产生异常的原因并且被转换为python字符串对象并存储在第二个全局变量中。

Another useful function is PyErr_SetFromErrno(), which only takes an exception argument and constructs the associated value by inspection of the global variable errno. The most general function is PyErr_SetObject(), which takes two object arguments, the exception and its associated value. You don't need to Py_INCREF() the objects passed to any of these functions.

另一个比较有用的函数是PyErr_SetFromErrno(),它只有一个参数,代表异常;通过检查全局便来那个errno来创建异常相关信息的值。最常用的函数是PyErr_SetObject(),它有两个参数,一个是异常对象另一个是与异常相关的信息。在使用这些函数时,不需要使用Py_INCREF()来维护这些异常对象的计数。

You can test non-destructively whether an exception has been set with PyErr_Occurred(). This returns the current exception object, or NULL if no exception has occurred. You normally don't need to call PyErr_Occurred() to see whether an error occurred in a function call, since you should be able to tell from the return value.

可以通过使用函数PyErr_Occurred()来测试是否有异常发生,发生时返回异常对象,如果返回NULL则代表没有异常发生。

When a function f that calls another function g detects that the latter fails, f should itself return an error value (usually NULL or -1). It should not call one of the PyErr_*() functions -- one has already been called by g. f's caller is then supposed to also return an error indication to its caller, again without calling PyErr_*(), and so on -- the most detailed cause of the error was already reported by the function that first detected it. Once the error reaches the Python interpreter's main loop, this aborts the currently executing Python code and tries to find an exception handler specified by the Python programmer.

如果一个函数f调用另一个函数g,并且函数g在执行中发生了错误,那么f需要返回一个错误值,通常为NULL或是-1。此处不能再去调用形如PyErr_*() 的函数,因为它们已经在函数g中被调用了。以此类推,调用f的函数也一样不能调用形如PyErr_*() 的函数。

To ignore an exception set by a function call that failed, the exception condition must be cleared explicitly by calling PyErr_Clear(). The only time C code should call PyErr_Clear() is if it doesn't want to pass the error on to the interpreter but wants to handle it completely by itself (possibly by trying something else, or pretending nothing went wrong).

如果需要忽略在调用一个函数时发生的错误,那么需要显式的调用PyErr_Clear(),在C代码中调用该函数的唯一理由就是不希望将该错误传入解释器而希望自己在C代码中处理。

Every failing malloc() call must be turned into an exception -- the direct caller of malloc() (or realloc()) must call PyErr_NoMemory() and return a failure indicator itself. All the object-creating functions (for example, PyInt_FromLong()) already do this, so this note is only relevant to those who call malloc() directly.

每一次直接调用malloc函数如果发生错误的话都要引发一个异常,调用PyErr_NoMemory()并且返回一个错误引用。其它创建的对象已经在内部这样做了所以不需要手工添加这个步骤。

Also note that, with the important exception of PyArg_ParseTuple() and friends, functions that return an integer status usually return a positive value or zero for success and -1 for failure, like Unix system calls.

当返回一个整数值表示状态时,通常返回一个正数或者0表示成功,返回-1表示失败

Finally, be careful to clean up garbage (by making Py_XDECREF() or Py_DECREF() calls for objects you have already created) when you return an error indicator!

The choice of which exception to raise is entirely yours. There are predeclared C objects corresponding to all built-in Python exceptions, such as PyExc_ZeroDivisionError, which you can use directly. Of course, you should choose exceptions wisely -- don't use PyExc_TypeError to mean that a file couldn't be opened (that should probably be PyExc_IOError). If something's wrong with the argument list, the PyArg_ParseTuple() function usually raises PyExc_TypeError. If you have an argument whose value must be in a particular range or must satisfy other conditions, PyExc_ValueError is appropriate.

返回什么样的异常完全取决于你,已经存在了许多声明好的C语言对象来对应所有的python异常。

You can also define a new exception that is unique to your module. For this, you usually declare a static object variable at the beginning of your file:

你也可以自己定义新的异常,如果要那样做的话,你需要在你源文件的开头进行如下的声明:

 


and initialize it in your module's initialization function (initspam()) with an exception object (leaving out the error checking for now):

并且在你的初始化函数中对这个异常进行初始化

 


Note that the Python name for the exception object is spam.error. The PyErr_NewException()

function may create a class with the base class being Exception (unless another class is

passed in instead of NULL), described in the Python Library Reference under ``Built-in

Exceptions.

 

注意此处该异常被命名为spam.error。 PyErr_NewException()函数以Exception为基类创建新的异常类,如果要

指定其它基类,需要用基类的名字代替NULL。

 

Note also that the SpamError variable retains a reference to the newly created exception

class; this is intentional! Since the exception could be removed from the module by external

code, an owned reference to the class is needed to ensure that it will not be discarded,

causing SpamError to become a dangling pointer. Should it become a dangling pointer, C code

which raises the exception could cause a core dump or other unintended side effects.

 

同时注意SpamError变量保留了一个对新创建的异常对象的引用,它是内部的。因为外部代码可以从模块中移除异常,所以

保留一个对该异常对象的引用可以保证该对象不被丢弃。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值