20

저는 파이썬 인터프리터를 C 프로그램에 내장하고 있습니다. 그러나 PyRun_SimpleString()을 통해 일부 python 스크립트를 실행하는 동안 무한 루프로 실행되거나 너무 오래 실행될 수 있습니다. PyRun_SimpleString("while 1: pass"); 주 프로그램 차단을 방지하기 위해 인터프리터를 스레드로 실행할 수 있다고 생각했습니다.임베디드 파이썬 중지

전체 프로세스를 죽이지 않고 스레드에서 실행되는 임베디드 인터프리터에서 python 스크립트 실행을 중단하려면 어떻게합니까?

인터프리터에 예외를 전달할 수 있습니까? 신호를 듣는 다른 스크립트로 스크립트를 래핑해야합니까?

PS : 나는 별도의 프로세스에서 파이썬을 실행할 수 있지만 내가 원하는 것이 아니다 - ...


업데이트는 최후의 수단이 아닌 경우 : 그래서

을, 그것을 지금 일합니다. Denis Otkidach, 다시 한번 감사드립니다!

이 권리가 있다면, 두 가지를해야합니다. 즉, PyRun_SimpleString()이 실행중인 것과 동일한 스레드에서 인터프리터에게 중지하고 return -1을 알려주십시오.

중지하려면 하나는 가능성이 있습니다 : PyErr_SetString(PyExc_KeyboardInterrupt, "...") 또는 PyErr_SetInterrupt() - 첫 번째 명령은 몇 가지 더 많은 명령을 실행 한 다음 나중 명령을 중지하고 나중에 실행을 중지합니다.

return -1Py_AddPendingCall()을 사용하면 파이썬 실행에 함수 호출을 삽입 할 수 있습니다. 문서는 버전 2.7 및 3.1 이후로 언급하고 있지만 이전 Pythons에서도 실행됩니다 (여기에서는 2.6). 2.7과 3.1에서 GIL (?)을 획득하지 않고 호출 할 수 있다는 의미이므로 스레드로부터 안전해야합니다.

int quit() { 
    PyErr_SetInterrupt(); 
    return -1; 
} 

답변

10

Py_AddPendingCall()을 사용하면 다음 검사 간격에서 호출 할 함수 발생 예외를 추가 할 수 있습니다 (자세한 내용은 sys.setcheckinterval()의 문서 참조). 여기에 (나를 위해 일을 수행하지만, 아마도 당신이 필요하지 않습니다) Py_Exit() 호출을 예입니다, Py_Finalize() 또는 PyErr_Set*()의로 교체 :

int quit(void *) { 
    Py_Exit(0); 
} 


PyGILState_STATE state = PyGILState_Ensure(); 
Py_AddPendingCall(&quit, NULL); 
PyGILState_Release(state); 

이 어떤 순수 파이썬 코드를 충분합니다. 그러나 일부 C 함수는 한 번의 작업으로 잠시 동안 실행할 수 있습니다 (장기 실행 regexp 검색을 사용한 예제가 있지만 여전히 관련성이 있는지는 확실하지 않습니다).

+0

이 모양은 매우 흥미롭지 만 매우 최신 Python에서는 그렇지 않습니까? (2.7 알파는 오늘 나온 것입니다.) 그러나 파이썬 3.1로 업그레이드 할 수 있습니다. Py_AddPendingCall()을 통해 어떤 함수를 등록해야합니까? 'PyErr_SetString()'? 'Py_Exit()'? 'Py_Finalize()'? –

+0

Py_AddPendingCall은 적어도 Python 2.0부터 존재합니다 (ceval.h에 정의되어 있음).내 대답에 예제 코드를 추가했습니다. –

+0

감사! 그것은 작동합니다! –

1

잘 파이썬 인터프리터가 삽입 프로그램에서 별도의 스레드에서 실행되어야 할 것이다 또는 당신은 단순히 통역을 방해 할 수있는 기회를 얻을하지 않습니다 :

그래서 하나가 울부 짖는 소리의 예를 다시 작성할 수 있습니다.

아마도 파이썬 API 예외 호출 중 하나를 사용하여 인터프리터에서 예외를 트리거 할 수 있습니까?