标题:Python/C 异常的问题
只看楼主
xu541456
Rank: 2
等 级:论坛游民
威 望:1
帖 子:5
专家分:15
注 册:2016-6-10
 问题点数:0 回复次数:1 
Python/C 异常的问题
我在将python嵌入到C里面遇到一个这样的问题。
我定义了一个PythonNode的新类型,这是一个C++中的树结构
我在定义PythonNode的成员函数,这个函数的参数是一个回调函数,代码如下:

PyObject* PythonNode::Node_enumerateChildren(NodeObject* self, PyObject* args)
{
    PyObject* visitor;
    if (!PyArg_ParseTuple(args, "O", &visitor))
        return NULL;
    try
    {
        self->node.enumerateChildren([visitor](Node child)
        {
            NodeObject* childNode = (NodeObject*)NodeType.tp_alloc(&NodeType, 0);
            childNode->node = child;
            PyObject_CallFunction(visitor, "O", childNode);
            if (PyErr_Occurred())
            {
                //PyErr_Clear();
                throw BreakHere();
            }
        });
    }
    catch (BreakHere){}

    Py_RETURN_NONE;
}
而在python中调用enumerate_children需要写一个回调函数如下:
class BreakHere(BaseException):
  pass

find_node = None
def find_one(child):
    find_node = child
    raise Break_Here()  #这个是我自定义的异常

try:
    node.enumerate_children(find_one)
except Break_Here:
    pass
整个的调用流程是,python中会调用enumerate_children,而这个函数的实现在C中,
而C中enumerate_children的具体实现是一个遍历,遍历的过程中逐个的调用python中的设置回调函数find_one。
而find_one会抛出异常,我希望当其抛出异常时中断所有的操作,捕捉我想要的一个结果。
但事实上python的try-except没有起到任何作用,因为在调用enumerate_children直接会报错,提示这个函数返回的是一个error set。
请问有没有大神能够解决这个问题
搜索更多相关主题的帖子: Python 异常 node 函数 调用 
2017-12-29 11:47
xu541456
Rank: 2
等 级:论坛游民
威 望:1
帖 子:5
专家分:15
注 册:2016-6-10
得分:0 
回复 楼主 xu541456
我另写了一个demo简化了这个问题:
我参考Python的帮助文档python/c嵌入的例子写了一个用C自定义了个noddy.Noddy的新类型。
noddy.Noddy有一个成员函数name,原本是没有参数,我现在添加一个参数,这个参数是一个回调函数,函数内部会执行这个回调函数:
static PyObject *
Noddy_name(Noddy* self, PyObject* args)
{
    PyObject* func;
    if (!PyArg_ParseTuple(args, "O", &func))
        return NULL;
    PyObject_CallFunction(func, "i", 3); #这里执行了传入的回调函数
    if (self->first == NULL) {
        PyErr_SetString(PyExc_AttributeError, "first");
        return NULL;
    }
    if (self->last == NULL) {
        PyErr_SetString(PyExc_AttributeError, "last");
        return NULL;
    }
   
    return PyUnicode_FromFormat("%S %S", self->first, self->last);
}
而在python代码中导入了新定义的类型,代码如下:
from noddy import *
class MyException(BaseException):
        pass

def func(i):
        print(i)
        raise MyException()
   
one = Noddy()
try:
        one.name(func) #将func作为one.name的回调函数,则会报错
        #func(3) #直接调用这样是没有问题的。
except MyException: #如果写成 except BaseException: 或者 except: 都不会报错。
        pass
总结问题就是,func函数如果作为新定义类型的毁掉函数执行,抛出的异常,只能够通过except BaseException或者except才能捕捉到,
否则是捕捉不到的,我不知道这是不是python本身的一个BUG。
期望有人能够解答。


[此贴子已经被作者于2017-12-30 13:51编辑过]

2017-12-30 13:46



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-483826-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.258102 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved