나는 Python 인터프리터를 포함시키고 자하는 C++/Qt 응용 프로그램을 가지고 있습니다. QThread에서 파이썬을 호출하고 싶지만 전역 인터프리터 잠금 (GIL)을 얻기 위해 PyGILState_Ensure()를 호출하는 라인에서 교착 상태가 발생합니다.QThread가 PyGILState_Ensure()를 통해 Python GIL을 얻으려고 할 때 교착 상태가 발생합니다.
내가 here 주어진 권고 다음, 이는 아래의 최소 똑바로 앞으로 예제를 제공합니다:
//main.cpp:
#include <QCoreApplication>
#include <QThread>
#include "Worker.h"
void startThread()
{
QThread* thread = new QThread;
Worker* worker = new Worker();
worker->moveToThread(thread);
QObject::connect(thread, SIGNAL(started()), worker, SLOT(process()));
QObject::connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
QObject::connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Py_Initialize();
startThread();
Py_FinalizeEx();
return a.exec();
}
//Worker.h:
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include "Python.h"
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr) : QObject(parent) {}
Q_SIGNALS:
void finished();
public Q_SLOTS:
void process()
{
qDebug("Calling Python");
PyGILState_STATE gstate = PyGILState_Ensure();
PyRun_SimpleString("print(\"hello\")");
PyGILState_Release(gstate);
qDebug("Done calling Python");
Q_EMIT finished();
}
};
#endif // WORKER_H
일부 추가 의견 :
- 참고 : .PRO 파일이 라인을 포함을
CONFIG += no_keywords
, 파이썬 헤더와 이름 충돌을 피하기 위해. - 스레드가 PyGILState_Ensure()를 호출 할 때 실행을 중지하는 동안 주 스레드는 계속 제한되지 않는다는 점에 유의해야합니다.
return a.exec();
을return 0;
으로 변경하면 프로그램이 종료됩니다. (교착 상태는 사용하기에 잘못된 용어입니다.) - 파이썬에서 스레드를 만드는 데 관심이 없습니다. QThread에서 주어진 Python 스크립트를 직접적으로 순차적으로 호출하고자합니다.
- 나는 다른 similarquestions을 읽었지만, 거기에는 미묘한 차이가 있다고 생각되어 거기에서 주어진 답에서 나의 문제를 해결할 수 없었다. 또한, 내가 Python/C API documentation을 올바르게 이해한다면, 필요하지 않아야하는
PyEval_InitThreads()
으로 전화를 걸 것을 권고하는 것에 혼란 스럽습니다.
어떻게 당신이 죽은 잠금입니다 알고 :
여기문제를 해결
main.cpp
의 업데이트 된 버전은? 응용 프로그램이 작동하지 않을 때 디버거를 사용하여 모든 스레드 호출 스택을 검사합니다. –PyGILState_Ensure()가 호출 된 줄에서 디버거를 멈추고 거기에서 한 줄 앞으로 나가면 프로그램이 잠 깁니다. 나는. 스레드가 PyGILState_Ensure() 내 어딘가에 갇히게됩니다. – andreasdr