停止嵌入式 Python [英] Stopping embedded Python

查看:27
本文介绍了停止嵌入式 Python的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将 Python 解释器嵌入到 C 程序中.然而,在通过 PyRun_SimpleString() 运行某些 python 脚本时,可能会遇到无限循环或执行时间过长的情况.考虑 PyRun_SimpleString("while 1: pass"); 为了防止主程序阻塞,我想我可以在线程中运行解释器.

I'm embedding Python interpreter to a C program. However, it might happen that while running some python script via PyRun_SimpleString() will run into infinite loop or execute for too long. Consider PyRun_SimpleString("while 1: pass"); In preventing the main program to block I thought I could run the interpreter in a thread.

如何在不杀死整个进程的情况下停止在线程中运行的嵌入式解释器中执行 python 脚本?

How do I stop executing the python script in embedded interpreter running in a thread without killing the whole process?

是否可以将异常传递给解释器?我应该将脚本包装在其他一些可以监听信号的脚本下吗?

Is it possible to pass an exception to the interpreter? Should I wrap the script under some other script which would listen to signals?

PS:我可以在单独的进程中运行 python 但这不是我想要的 - 除非这是最后的手段......

PS: I could run the python in a separate process but this is not what I want - unless it is the last resort...

更新:

所以,它现在可以工作了.再次感谢 Denis Otkidach!

So, it works now. Thank you Denis Otkidach, once again!

如果我没看错,你必须做两件事:告诉解释器停止并在你的 PyRun_SimpleString() 运行的同一个线程中return -1.

If I see this right, you have to do two things: tell the interpreter to stop and return -1 in the same thread as your PyRun_SimpleString() is running.

要停止,有几种可能性:PyErr_SetString(PyExc_KeyboardInterrupt, "...")PyErr_SetInterrupt() - 第一个可能会让 Python 运行一些指令越多就停止,后面的指令立即停止执行.

To stop, one has a few possibilities: PyErr_SetString(PyExc_KeyboardInterrupt, "...") or PyErr_SetInterrupt() - the first one might leave Python running a few more instructions and then it stops, the later one stops the execution immediately.

return -1,您可以使用Py_AddPendingCall() 将函数调用注入到 Python 执行中.文档从 2.7 和 3.1 版开始就提到了它,但它也可以在早期的 Python 上运行(此处为 2.6).从 2.7 和 3.1 开始,它也应该是线程安全的,这意味着您可以在不获取 GIL (?) 的情况下调用它.

To return -1 you use Py_AddPendingCall() to inject a function call into Python execution. The docs are mentioning it since version 2.7 and 3.1 but it runs on earlier Pythons as well (2.6 here). From 2.7 and 3.1 it should also be thread-safe, meaning you can call it without acquiring GIL (?).

所以我们可以重写下面的例子:

So one could rewrite the example bellow:

int quit() {
    PyErr_SetInterrupt();
    return -1;
}

推荐答案

您可以使用 Py_AddPendingCall() 添加一个函数,该函数引发异常以在下一个检查间隔调用(请参阅 上的文档sys.setcheckinterval() 了解更多信息).这是一个带有 Py_Exit() 调用的例子(它对我有用,但可能不是你需要的),用 Py_Finalize() 之一替换它>PyErr_Set*():

You can use Py_AddPendingCall() to add a function raising exception to be called on next check interval (see docs on sys.setcheckinterval() for more info). Here is an example with Py_Exit() call (which does works for me, but probably is not what you need), replace it with Py_Finalize() or one of PyErr_Set*():

int quit(void *) {
    Py_Exit(0);
}


PyGILState_STATE state = PyGILState_Ensure();
Py_AddPendingCall(&quit, NULL);
PyGILState_Release(state);

这对于任何纯 python 代码应该足够了.但请注意,某些 C 函数可以作为单个操作运行一段时间(有一个长时间运行正则表达式搜索的示例,但我不确定它是否仍然相关).

This should be enough for any pure-python code. But note, that some C functions can run for a while as a single operation (there was an example with long running regexp search, but I'm not sure it's still relevant).

这篇关于停止嵌入式 Python的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆