繁体   English   中英

如何从C扩展中引发Python异常

[英]How to raise Python exception from a C extension

我想从C扩展中提升KeyboardInterrupt。

在C中,我通过下面的+ setup.py创建了一个名为siginfo的模块:

static void siginfo_handler(int signum, siginfo_t *siginfo, void *context) {
    printf("got signal from '%d'", siginfo->si_pid);

    //raise(PyExc_KeyboardInterrupt) <--- i want to raise keyboard interrupt here
}

static PyObject * siginfo_register(PyObject *self, PyObject *args) {
    struct sigaction act;
    memset(&act, '\0', sizeof(act));
    act.sa_sigaction = &siginfo_handler;
    act.sa_flags = SA_SIGINFO;
    sigaction(SIGINT, &act, NULL);

    PY_RETURN_NONE;
}

static PyMethodDef SiginfoMethods[] = {
   //blah blah filled out
};
PyMODINIT_FUNC initsiginfo(void) {
   //blah blah filled out
}

在Python中:

import siginfo
import os
siginfo.register()

print "talk to me with kill -SIGINT %d" % os.getpid()

try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    print 'got keybaord interrupt'

C扩展正在捕获SIGINT,但我不知道如何从中引发Python异常,以便我可以在Python代码中捕获它。

有任何想法吗?

编辑:
我发现我可以通过以下方式引发KeyboardInterrupt:

PyErr_SetString(PyExc_KeyboardInterrupt, "SIGINT received");

但如果我在信号处理程序中提升它,它确实会出错。

如果它在其他功能中被提升,它不会出错。

为什么我不能在信号处理程序中提出它?

在获取信号时,您只是处于执行Python代码的状态。 在提出错误之前,您需要获取GIL

static void siginfo_handler(int signum, siginfo_t *siginfo, void *context) {
    printf("got signal from '%d'\n", siginfo->si_pid);
    PyGILState_STATE gstate = PyGILState_Ensure();
    PyErr_SetString(PyExc_KeyboardInterrupt, "SIGINT received");
    PyGILState_Release(gstate);
}

您不能从信号处理程序内部调用任意Python C / API函数。 信号处理程序的功能非常有限。 有关详细信息,请参阅此处此处

Python通过一个非常简单的信号处理程序来处理它,它将volatile sig_atomic_t类型的变量设置为1.如果设置为1,解释器会定期检查此异常,将Python异常作为常规控制流的一部分。

主要问题是解释器调用需要很长时间才能执行的C代码。 在C代码返回之前不会引发异常。

幸运的是,这种情况并不常发生,因为大多数系统调用在传递信号时都会中断。 在下面的程序中(与你的程序非常相似),对time.sleep()的调用将被信号中断,控件将返回Python代码,这将引发异常。

import time
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    print 'got keybaord interrupt'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM