我在尝试中止Python脚本时遇到问题,例如:
#!/usr/bin/python
import hello
hello.draw()
exit()
其中draw()是C函数。在这个函数中有一个循环来打印一些文本。我试过CTRL-C来突破它但它不起作用。 重要的是C代码无法修改!
有什么想法吗?
答案 0 :(得分:2)
我汇总了一个如何做到这一点的例子。它允许扩充功能并从中逃脱而无需修改它。例如,给定函数foo
(在test.h中为测试内联):
void foo() {
while(1); // never returns
}
您可以使用信号和siglongjmp
来玩游戏。但应注意you need to be very careful以确保您只在foo
内调用async safe个函数,或者在任何不安全的调用之后屏蔽信号并在屏蔽后取消屏蔽它们。
然后我们可以包装该函数并使用%exception
注入一些额外的代码以允许信号退出该函数:
%module test
%{
#include <setjmp.h>
#include <signal.h>
static sigjmp_buf timeout;
static void backout(int sig) {
siglongjmp(timeout, sig);
}
#include "test.h"
%}
%include <exception.i>
%exception {
if (!sigsetjmp(timeout, 1)) {
signal(SIGALRM,backout); // Check return?
$action
}
else {
// raise a Python exception
SWIG_exception(SWIG_RuntimeError, "Timeout in $decl");
}
}
void foo();
%exception;
允许我们写:
import signal
import test
signal.alarm(5)
test.foo()
考虑到有关异步安全功能的警告,其效果如预期。我在这里使用SIGALRM
因为它允许我将它全部保存在一个Python文件中。如果您愿意,可以使用其他线程/进程和其他信号。
如果你将我的例子中的SIGALRM更改为SIGINT(并且显然没有提出SIGALRM),那么它将适用于 Ctrl + C - 它之所以没有这是因为how the default Python signal handlers work。 Python使用的默认处理程序只是设置一个标志,并在底层调用将控制权返回给Python之后处理信号,这整齐地排除了整个异步安全问题。
答案 1 :(得分:0)
您需要为C函数提供一个中止它的方法 - 例如,它可以在其绘制循环中轮询全局状态标志。
答案 2 :(得分:0)
另一种可能性是停止该过程,然后终止它。在bash
命令行(Linux / MacOS)中,如下所示:
假设您启动脚本...
$ python3 example.py
...然后键入 control + Z 停止该过程。在方括号中查找数字,在这种情况下为1
。
[1]+ Stopped python3 example.py
现在,您可以使用kill
命令,然后在方括号中显示数字来终止该进程。
$ kill %1
[1]+ Terminated: 15 python3 example.py