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

查看:135
本文介绍了停止嵌入式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!

如果我看对了,您必须做两件事:告诉解释器停止运行,并且return -1与PyRun_SimpleString()正在运行的线程相同.

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函数可以作为单个操作运行一段时间(有一个示例运行长时间的regexp搜索,但我不确定它是否仍然有用).

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天全站免登陆