我有一个很小的 Python 脚本(在我看来)threading.Thread.start()
表现出意外,因为它不会立即返回。
在线程内我想调用一个方法boost::python
基于对象,不会立即返回。
为此,我将对象/方法包装如下:
import threading
import time
import my_boostpython_lib
my_cpp_object = my_boostpython_lib.my_cpp_class()
def some_fn():
# has to be here - otherwise .start() does not return
# time.sleep(1)
my_cpp_object.non_terminating_fn() # blocks
print("%x: 1" % threading.get_ident())
threading.Thread(target=some_fn).start()
print("%x: 2" % threading.get_ident()) # will not always be called!!
只要我一切正常之前运行一些代码 my_cpp_object.non_terminating_fn()
。如果我不这样做,.start()
将以与调用相同的方式阻塞.run()
直接会。
在调用之前只打印一行boost::python
功能还不够,但是例如打印两行或调用time.sleep()
makes start()
如预期立即返回。
你能解释一下这种行为吗?我该如何避免这种情况(除了打电话sleep()
在致电之前boost::python
功能)?
这种行为(就像在大多数情况下,当你相信解释器/编译器中存在错误时)不是 Python 中的错误,而是竞争条件涵盖了 Python 所带来的预期行为GIL(还讨论了here https://stackoverflow.com/questions/22138190/python-threading-thread-start-doesnt-return-control-to-main-thread).
一旦非Python函数my_cpp_object.non_terminating_fn()
启动后,GIL 在返回之前不会被释放,并阻止解释器执行任何其他命令。
So time.sleep(1)
无论如何这里没有帮助,因为下面的代码my_cpp_object.non_terminating_fn()
在 GIL 被释放之前不会被执行。
的情况下boost::python
当然,如果您可以修改 C/C++ 部分,您可以按照所述手动释放 GILhere https://wiki.python.org/moin/boost.python/HowTo.
一个小例子(来自上面的链接)可能看起来像这样(在 boost::python 包装器代码中)
class scoped_gil_release {
public:
inline scoped_gil_release() {
m_thread_state = PyEval_SaveThread();
}
inline ~scoped_gil_release() {
PyEval_RestoreThread(m_thread_state);
m_thread_state = NULL;
}
private:
PyThreadState * m_thread_state;
};
int non_terminating_fn_wrapper() {
scoped_gil_release scoped;
return non_terminating_fn();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)