gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-10-31 01:41:49 38 4
gpt4 key购买 nike

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

我看到的错误是:

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;
}

输出

--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() 调用都会导致错误输出。

编辑:

使 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"));

之后

PyEval_InitThreads();

关于python - 使用线程调用 Py_Finalize 时出现 AssertionError(仅限 3.X),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27844676/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com