限制嵌入式Python的执行时间

时间:2016-07-24 16:16:50

标签: python infinite-loop sandbox python-embedding

如果我将Python解释器嵌入到C或C ++程序中,就像在this example中那样,有没有办法限制解释器运行的时间?有没有什么可以阻止Python代码进入无限循环,从而阻止PyObject_CallObject(或等价物)返回?

同样,如果Python代码创建了一个新线程,是否还有什么可以阻止这个线程进入无限循环并永远运行?

3 个答案:

答案 0 :(得分:7)

正如您在the docs中所看到的,PyObject_CallObject没有限制函数运行时间的机制。我也知道没有Python C API函数可以暂停或终止解释器使用的线程。

因此,我们必须在如何阻止线程运行方面更具创造性。我可以想到你可以做到的3种方法(从最安全/最干净到最危险......

轮询您的主要申请

这里的想法是你的Python函数可以运行很长时间只是调用主应用程序中的另一个函数,使用C API来查看它是否应该关闭。一个简单的True / False结果可以让你优雅地终止。

这是最安全的解决方案,但要求您更改Python代码。

使用例外

由于您正在嵌入Interpreter,因此您已经在使用C API,因此可以使用PyThreadState_SetAsyncExc强制在违规线程中引发异常。您可以找到使用此API here的示例。虽然它是Python代码,但同样的功能可以在您的主应用程序中使用。

这个解决方案不太安全,因为它要求代码不要捕获异常并在之后保持可用状态。

使用操作系统终止线程

我不打算进入这个,因为它本身就是不安全的。有关原因的解释,请参阅Is there any way to kill a Thread in Python?

答案 1 :(得分:2)

如果在某些实时系统中需要控制滞后和抖动,请嵌入“StacklessPython” - 支持协同例程的Python。用于“Twisted Web Server”。

答案 2 :(得分:1)

我希望能够中断任何正在运行的Python代码块,包括取消无限循环或仅删除一些长时间运行的代码。在我的应用程序中,提交并评估了单线程Python代码。中断请求可以随时出现。这个问题和答案对于帮助我真正实现目标至关重要。

我使用2016年7月以来@Peter Brittain回答的中间方法。

启动Python引擎后,我使用Python代码中的threading包检索线程ID。我将其解析为c long值并将其保存。

中断功能实际上非常简单:
PyGILState_Ensure()
PyThreadState_SetAsyncExc(threadId, PyExc_Exception)使用我之前保存的线程ID和通用异常类型
PyGILState_Release()

因此,感谢您同时回答原始问题和Peter Brittain!