AssertionError (только 3.X) при вызове Py_Finalize с потоками

Я получаю сообщение об ошибке, когда я вызываю Py_Finalize () из C-API из другого C-потока, чем я сделал вызов 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-- 

Порядок основных вызовов () / with_thread () в основном не имеет значения, я могу даже включать эти строки несколько раз без влияния, каждый вызов with_thread () приводит к выходу ошибки.

Редактировать :

Создание threadState global, а затем изменение 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 более изолированным, как исходный пример, сохраняя совместимость потоков?

One Solution collect form web for “AssertionError (только 3.X) при вызове Py_Finalize с потоками”

Попробуйте добавить

 Py_DECREF(PyImport_ImportModule("threading")); 

после

 PyEval_InitThreads(); 
  • Возвращение объектов в Python из C
  • Является ли API-интерфейс python полностью совместимым с C ++?
  • Как работает PyArg_ParseTupleAndKeywords?
  • Как использовать Cython типизированные представления памяти для принятия строк из Python?
  • Как сделать копию модуля python во время выполнения?
  • easy_install терпит неудачу при ошибке «Не удалось найти скрипт установки» после бинарной загрузки?
  • Неустранимая ошибка: Python.h: Нет такого файла или каталога
  • ImportError: динамический модуль не определяет функцию init (initfizzbuzz)
  • Расширение python с помощью C: Передача списка в PyArg_ParseTuple
  • Как исследовать функцию, определенную в модуле расширения Cython C
  • Когда вызывается PyEval_InitThreads?
  • Python - лучший язык программирования в мире.