2

我正在尝试编写一个 C++ 类,该类调用一次执行一些 I/O 操作(文件、标准输出)的类的 Python 方法。我遇到的问题是我的类是从不同的线程调用的:有时是主线程,有时是不同的其他线程。显然,我尝试将这种方法应用于多线程本机应用程序中的 Python 调用。基本上一切都从 PyEval_AcquireLock 和 PyEval_ReleaseLock 或只是全局锁开始。根据此处的文档,当线程已被锁定时,就会发生死锁。当从主线程或其他阻止 Python 执行的线程调用我的类时,我遇到了死锁。

Python> Cfunc1() - C++ 函数在内部创建线程,导致在“我的类”中调用,它卡在 PyEval_AcquireLock 上,显然 Python 已经被锁定,即等待 C++ Cfunc1 调用完成......如果我完成就好了省略那些锁。当 Python 解释器准备好下一个用户命令时,它也可以正常完成,即当线程在后台调用 funcs 时 - 而不是在本机调用内部

我正在寻找一种解决方法。我需要区分是否允许全局锁定,即 Python 未锁定并准备好接收下一个命令...我尝试了 PyGIL_Ensure,不幸的是我看到挂起。

任何已知的 API 或解决方案?

(Python 2.4)

4

1 回答 1

2

除非您非常特殊地包装了您的 C++ 代码,否则当任何Python 线程调用您的 C++ 代码时,GIL 将被保留。你可以在你的 C++ 代码中发布它(如果你想做一些不需要任何 Python 交互的消耗任务),然后当你想做任何 Python 交互时必须再次获取它——请参阅文档:如果你只是在使用好的旧 C API,有宏,推荐的成语是

Py_BEGIN_ALLOW_THREADS
...Do some blocking I/O operation...
Py_END_ALLOW_THREADS

文档解释:

Py_BEGIN_ALLOW_THREADS 宏打开一个新块并声明一个隐藏的局部变量;Py_END_ALLOW_THREADS 宏关闭块。使用这两个宏的另一个好处是,当 Python 在没有线程支持的情况下编译时,它们被定义为空,从而节省了线程状态和 GIL 操作。

因此,在明确发布 GIL(最好是使用该宏)并需要再次以任何方式与 Python 交互之前,您不必获取 GIL(也不应该) 。(当文档说“一些阻塞 I/O 操作”时,它实际上可能是任何长时间运行的操作,没有任何 Python 交互)。

于 2010-06-07T01:08:43.617 回答