【问题标题】:When is PyEval_InitThreads meant to be called? [duplicate]PyEval_InitThreads 什么时候应该被调用? [复制]
【发布时间】:2013-02-17 00:38:27
【问题描述】:

我有点不知道什么时候应该打电话给PyEval_InitThreads。一般来说,我知道PyEval_InitThreads 必须在使用非 Python 线程(即在扩展模块中产生的线程)时调用。

但是,我很困惑PyEval_InitThreads 是用于嵌入 Python 解释器的 C 程序,还是用于导入 C 扩展模块的 Python 程序,或者两者兼而有之。

那么,如果我编写了一个内部启动线程的 C 扩展模块,我需要在初始化模块时调用PyEval_InitThreads 吗?

另外,PyEval_InitThreads implicitly acquires the Global Interpreter Lock。所以在调用PyEval_InitThreads 之后,大概GIL 必须释放,否则就会出现死锁。那么如何释放锁呢?阅读文档后,PyEval_ReleaseLock() 似乎是释放 GIL 的方式。但是,在实践中,如果我在 C 扩展模块中使用以下代码:

   PyEval_InitThreads();
   PyEval_ReleaseLock();

...然后在运行时 Python 中止:

Fatal Python error: drop_gil: GIL is not locked

那么用PyEval_InitThreads获取GIL后如何释放呢?

【问题讨论】:

  • 尝试不使用PyEval_ReleaseLock()。获得 GIL 是有充分理由的;在从 Python 调用其他 C API 函数之前释放它会崩溃。

标签: python c python-3.x python-c-api python-c-extension


【解决方案1】:

大多数应用程序根本不需要知道PyEval_InitThreads()

您应该使用它的唯一情况是,如果您的嵌入应用程序或扩展模块将从多个线程进行 Python C API 调用它在 Python 之外产生了自己

不要在稍后将进行 Python C API 调用的任何线程中调用 PyEval_ReleaseLock()(除非您在这些线程之前重新获取它)。在这种情况下,您应该真正使用 Py_BEGIN_ALLOW_THREADSPy_END_ALLOW_THREADS 宏。

【讨论】:

  • 我不明白这个答案。假设您将 Python 嵌入到 C 程序中,并且您有 20 个工作线程,它们应该调用 PyEval_InitThreads,以及每个工作线程如何在它停止执行其他操作时释放锁,以便其他需要执行 Python 工作的线程可以获得 GIL ?
  • @DougN,是的,我同意。答案很模糊(不幸的是 Python 文档本身也是如此)
  • 如果您将 Python 嵌入到 C 程序中,请在初始化嵌入式 Python 解释器时为整个程序调用一次,然后再让它执行您的第一个 Python 代码。
猜你喜欢
  • 1970-01-01
  • 2019-12-26
  • 2013-10-31
  • 2014-05-19
  • 2011-06-16
  • 2014-09-06
  • 1970-01-01
  • 2012-03-18
  • 1970-01-01
相关资源
最近更新 更多