2017-02-03 2 views
0

Как и обсуждаемый вопрос here, мне нужно вызвать асинхронный код Python из многопоточной программы на C++. Но это не будет основной поток (тот, который вызывает Py_Initialize() и PyEval_InitThreads()), который вызовет выполнение python.Многопоточные вызовы на python из C API

Я не знаю, как управлять звонками PyEval_SaveThread() и PyEval_RestoreThread(): безопасно позвонить PyEval_SaveThread() и оставить извлеченное состояние потока не используется? Был бы смысл позвонить PyThreadState_Clear()?

Я хотел бы управлять только GIL, используя PyGILState_Ensure() и PyGILState_Release(), если это возможно.

Спасибо!

Edit 1:

Я попробовал, что в основном потоке:

PyEval_InitThreads(); 
Py_Initialize(); 

PyThreadState* _state = PyEval_SaveThread(); 
PyEval_AcquireLock(); 
PyThreadState_Clear(_state); 
PyEval_ReleaseLock(); 

Я получаю ошибку сегментации.

Edit 2:

я не нашел способ отказаться от PyThreadState только после PyEval_SaveThread(), но я подтверждаю, что можно иметь дело только с PyGILState_Ensure() и PyGILState_Release() защитить выполнение питона как только поток будет сохранен, независимо от того, остаемся ли мы в том же потоке или нет.

В конце, кажется, необходимо восстановить поток до завершения.

Edit 3:

  • Сегодня, используя Python 2.7, переход на Python 3 в ближайшем будущем.
  • относительно ошибки сегментации при очистке состояния потока python, нет сообщения об ошибке. При завершении будет обнаружена ошибка seg. Python может догадаться, что он должен закрыть основной поток, который я только что очистил?
  • Когда программа завершается, если ошибка не была выполнена, выполнение python завершено, и тогда она должна быть в состоянии хорошо финализировать. Это то, как он работает, когда я не очищаю состояние потока.
+0

Несколько вопросов: 1. Какая версия Python предназначена для этого? 2. Есть ли сообщение об ошибке? 3. Что происходит, когда ваша программа завершается? например вы хотели бы завершить python. – sterin

+0

@ user99279, спасибо, я добавил информацию в вопрос ... – Grumot

ответ

0

Я также изучаю, поэтому информация здесь может быть неполной, но по крайней мере я мог бы преодолеть ошибку сегментации.

Использование API Python 2.7 C.

В основной():

Py_Initialize(); 
PyEval_InitThreads(); 

// IMPORTNT: You must release before launching threads 
PyEval_ReleaseLock(); 

// Create/Start threads here 

// Wait until threads ends 

// Before finishing, acquire the GIL 
PyGILState_STATE gstate = PyGILState_Ensure(); 
Py_Finalize(); 

В методе выполнения вашего потока:

PyGILState_STATE gstate = PyGILState_Ensure(); 

// Your Python work, i.e: 
PyRun_SimpleString("print('Hello from Thread')"); 

PyGILState_Release(gstate); 

Примечание: В настоящее время у меня есть некоторые проблемы, когда код Python, что я звоню из мои потоки включают в себя импорт модулей и создание объектов pyplot, но это еще одна история.

+0

Спасибо, хороший обходной путь, непосредственно освобождающий замок сначала ... Я проверю его очень скоро; это звучит многообещающе – Grumot

Смежные вопросы