使用线程调用 Py_Finalize 时出现 AssertionError(仅限 3.X)

2023-11-29

当我从与 python 调用不同的 C 线程调用 C-API 的 Py_Finalize() 时,我收到错误输出。

我看到的错误是:

Exception ignored in: <module 'threading' from 'C:\\Python34-32\\Lib\\threading.py'>
Traceback (most recent call last):
  File "C:\Python34-32\Lib\threading.py", line 1289, in _shutdown
    assert tlock.locked()
AssertionError:

这只发生在 Python 3.X 中(使用 3.4.2 测试),在 Python 2.7 中完全相同的代码没有任何问题。

下面是一个最小的示例,显示使用 C 线程时会发生这种情况,但当所有事情都发生在单个 C 线程上时则不会:

#include <iostream>
#include <fstream>
#include <thread>
#include <cassert>

#include <Python.h>

void make_file()
{
   std::fstream file("my_test.py", std::ios::out);
   file << 
      "import threading\n"   << 
      "def my_function():\n" << 
      "    pass\n"             ;
   file.close();
}

void exec()
{
   PyGILState_STATE gstate = PyGILState_Ensure();
   PyObject* pdict = PyDict_New();
   PyDict_SetItemString(pdict, "__builtins__", PyEval_GetBuiltins());

   PyRun_String("import my_test", Py_file_input, pdict, pdict);
   PyRun_String("my_test.my_function()", Py_file_input, pdict, pdict);
   assert(!PyErr_Occurred());
   PyGILState_Release(gstate);
}

void basic()
{
   std::cout << "--Starting Basic--" << std::endl;

   Py_Initialize();
   PyEval_InitThreads();
   PyThreadState* threadState = PyEval_SaveThread();

   exec();

   PyEval_RestoreThread(threadState);
   Py_Finalize();

   std::cout << "--Basic Complete--" << std::endl;
}

void with_thread()
{
   std::cout << "--Starting With Thread--" << std::endl;

   Py_Initialize();
   PyEval_InitThreads();
   PyThreadState* threadState = PyEval_SaveThread();

   std::thread t(exec);
   t.join();

   PyEval_RestoreThread(threadState);
   Py_Finalize();

   std::cout << "--With Thread Complete--" << std::endl;
}

int main(int argc, char* argv[])
{
   make_file();
   basic();
   with_thread();

   return 0;
}

output

--Starting Basic--
--Basic Complete--
--Starting With Thread--
Exception ignored in: <module 'threading' from 'C:\\Python34-32\\Lib\\threading.py'>
Traceback (most recent call last):
  File "C:\Python34-32\Lib\threading.py", line 1289, in _shutdown
    assert tlock.locked()
AssertionError:
--With Thread Complete--

main 中 basic()/with_thread() 调用的顺序并不重要,我什至可以多次包含这些行而不会产生任何影响,每个 with_thread() 调用都会导致错误输出。

Edit :

使 threadState 全局化,然后将 exec 更改为:

void exec()
{
   //PyGILState_STATE gstate = PyGILState_Ensure();
   PyEval_RestoreThread(threadState); 
   PyObject* pdict = PyDict_New();
   PyDict_SetItemString(pdict, "__builtins__", PyEval_GetBuiltins());

   PyRun_String("import my_test", Py_file_input, pdict, pdict);
   PyRun_String("my_test.my_function()", Py_file_input, pdict, pdict);
   assert(!PyErr_Occurred());
   //PyGILState_Release(gstate);
   threadState = PyEval_SaveThread();
}

导致错误消失,但是我有一个全局值,我需要在我的库的用户之间进行协调(在我的实际代码中, exec() 函数可以由任何人编写,并且我有更多的初始化内容跑步)。关于如何使 GIL 抓取像原始示例一样更加隔离,同时保持线程兼容性,有什么见解吗?


尝试添加

Py_DECREF(PyImport_ImportModule("threading"));

after

PyEval_InitThreads();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用线程调用 Py_Finalize 时出现 AssertionError(仅限 3.X) 的相关文章

随机推荐

  • 如何在 x64 Visual C++ 中执行裸函数和内联汇编程序

    我正在使用裸函数和内联汇编器代理方法调用 declspec naked void ProxyFunction static const unsigned int addressofRealFunction 0x0041b200 asm jm
  • 如何在 ASM 8086 中弹奏和弦?

    我想知道在集会上同时弹奏超过 1 个音符的最佳方式是什么 如果可以的话 请添加一个过程来解释您的答案 谢谢 橙色 下一个代码是很久以前在EMU8086和Windows XP中编写的程序 当时运行 现在我有 Windows 8 64 位 但它
  • 类型错误:__init__() 恰好需要 1 个参数(给定 3 个)pyXML

    我最近开始学习如何使用python来解析xml文件 我的教程来自http pyxml sourceforge net topics howto node12 html 当我运行以下代码时 出现错误 Traceback most recent
  • 如何在Android中捕获音频的输出流?

    我是开发新手 我尝试在 Android 平台上创建一个均衡器 如何在 Android 上捕获输出音频流 我只需要获取从我的应用程序发出的音频信息 我已经搜索了www developers android com 但没有找到任何信息 目前 A
  • 如何在iOS中获取丰富的电池信息?

    我想知道是否可以在 iOS 中接收有关电池的信息 例如 容量 mA 电压 V 循环次数 我知道 UIDevice 类 但电池电量不是我想要的 Try UI设备监听器 它基本上窃取了整个电池数据字典UIDevice不使用任何私有 API 它暴
  • 基础5:选项卡回调

    升级到 Foundation 5 如何向我的选项卡添加回调 看代码好像不太可能 它可以与 Foundation 4 中的部分兼容 他们说回调有两种方式http foundation zurb com docs components tabs
  • Lua __lt 不与 table.sort 一起使用,即使它已定义

    我有一个继承自实体类的图块类 实体类定义了 lt 虽然我可以从图块类访问它 但当我尝试将所有图块放入 table sort 时 出现 比较两个表 错误 实体类 local Entity function Entity New pos obj
  • plt。在子图中仅适用于一个图

    我是 python 新手 所以我希望我的问题足够好 我正在尝试根据两个不同的数据框创建两个子图 我的问题是 当我尝试定义标题和 xlim 时 它仅适用于一个图 这是我的脚本 fig axes plt subplots 1 2 figsize
  • Android Camera2 API 拉伸预览

    我正在使用 Google 示例项目 但如果不拉伸它 我似乎无法让预览正常工作 public void setAspectRatio int width int height if width lt 0 height lt 0 throw n
  • 如何消除 Jquery 中的冲突?

    我是 JQuery 新手 我在我的页面中使用了 2 个 jQueries 对于第一个 JQuery 我的脚本是这样的 现在 当我像这样使用第二个 jQuery 时 我丢失了第一个 jQuery 无法加载
  • Clearcase:将子分支移动到主分支

    在clearcase中 我开始在一个名为的分支上工作main release4 release5 在我开始工作后 release4 被合并到 main 中 我的同事开始开发 main release5 无论如何我可以移动我的main rel
  • 如果两个可能条件中的任何一个成立,则 maven-antrun-plugin 跳过目标

    我可以通过以下方式将两个属性 A 和 B 传递给 maven mvn test DA true or mvn test DB true 如果定义了 A 或 B 我希望跳过目标 我发现当只考虑A时这是可能的
  • 删除Delphi中标签之间变量子字符串的所有实例

    我正在将 HTML 中的可读文本提取到字符串中 并且需要删除之间的现有文本标签 实现这一目标最有效的方法是什么 现在我正在这样做 function RemoveIEScripts const s string string var i In
  • 如何在 Linux Mint 上防止一致的 java 暂停模式

    我有一个在 Linux Mint 上运行的 Java 应用程序 每一分钟 程序都会显示出非常明显的减慢 暂停 停顿时间持续 3 到 4 秒 当我们运行同一程序的更多实例时 它们也会每分钟暂停 3 到 4 秒 每个节目在一分钟的不同秒停止 最
  • 通过 Google Apps 帐户通过 C# 发送电子邮件

    我有一个标准的 Google Apps 帐户 我已通过 Google Apps 设置了自定义域 当我使用 Gmail 界面时 我能够通过 Google Apps 成功发送和接收电子邮件 但是 我想通过代码发送电子邮件 为了尝试这个 我一直在
  • 运营转型库?

    我正在寻找一个库 它允许我在多个用户之间实时同步文本 ala Google Docs 我偶然发现了运营转型 它似乎符合我的需求 话虽如此 我了解 OT 的要点 但不了解 OT 的数学或实施 因此 我想知道是否有一个拖放 JavaScript
  • 如果不可用,Schema.org dateModified 是否应该有一些默认值?

    对于 Schema orgArticle我收到错误https developers google com structured data testing tool for dateModified 建议使用 dateModified 字段
  • 搞乱编码和 XslCompiledTransform

    我正在搞乱编码 一方面 我有一个以 UTF 8 格式响应我的 url 我非常确定 感谢 firebug 插件 我使用以下代码打开读取 UTF 8 格式内容的 url StreamReader reader new StreamReader
  • 姜戈 CSRF 403

    获取 CSRF 403 下面的 console log 语句确认我正在获取令牌 我正在将请求提交到本地服务器上的同一域 internal csrfToken cookie csrftoken internal csrfSafeMethod
  • 使用线程调用 Py_Finalize 时出现 AssertionError(仅限 3.X)

    当我从与 python 调用不同的 C 线程调用 C API 的 Py Finalize 时 我收到错误输出 我看到的错误是 Exception ignored in