code - Detener Python incrustado
boost python c (2)
Estoy incorporando el intérprete de Python a un programa de C. Sin embargo, puede suceder que mientras se ejecuta algún script de Python a través de PyRun_SimpleString()
se ejecutará en un bucle infinito o se ejecutará durante demasiado tiempo. Considere PyRun_SimpleString("while 1: pass");
Al evitar que el programa principal se bloquee, pensé que podía ejecutar el intérprete en un hilo.
¿Cómo detengo la ejecución de la secuencia de comandos de Python en un intérprete integrado que se ejecuta en un hilo sin terminar todo el proceso?
¿Es posible pasar una excepción al intérprete? ¿Debería envolver el guión bajo otro guión que escucharía señales?
PD: podría ejecutar la pitón en un proceso separado, pero esto no es lo que quiero, a menos que sea el último recurso ...
Actualizar:
Por lo tanto, funciona ahora. Gracias Denis Otkidach, una vez más!
Si veo esto correctamente, tiene que hacer dos cosas: decirle al intérprete que se detenga y que return -1
en el mismo hilo en el que se está ejecutando su PyRun_SimpleString ().
Para parar, uno tiene algunas posibilidades: PyErr_SetString(PyExc_KeyboardInterrupt, "...")
o PyErr_SetInterrupt()
: el primero puede dejar a Python ejecutando algunas instrucciones más y luego se detiene, el último detiene la ejecución inmediatamente.
Para return -1
, usa Py_AddPendingCall()
para inyectar una llamada de función en la ejecución de Python. Los documentos lo mencionan desde la versión 2.7 y 3.1, pero también se ejecuta en Pythons anteriores (2.6 aquí). Desde 2.7 y 3.1 también debe ser seguro para subprocesos, lo que significa que puede llamarlo sin adquirir GIL (?).
Así que uno podría reescribir el siguiente ejemplo:
int quit() {
PyErr_SetInterrupt();
return -1;
}
Bueno, el intérprete de Python tendría que estar ejecutándose en un subproceso separado del programa de incrustación o simplemente nunca tendrá la oportunidad de interrumpir al intérprete.
Cuando tienes eso, ¿quizás puedas usar una de las llamadas de excepción de la API de Python para activar una excepción en el intérprete? Ver las excepciones de la API de Python C
Puede usar Py_AddPendingCall()
para agregar una función que Py_AddPendingCall()
una excepción a la que se llamará en el siguiente intervalo de verificación (consulte la documentación en sys.setcheckinterval()
para obtener más información). Aquí hay un ejemplo con la llamada Py_Exit()
(que funciona para mí, pero probablemente no es lo que necesita), reemplácelo con Py_Finalize()
o uno de PyErr_Set*()
:
int quit(void *) {
Py_Exit(0);
}
PyGILState_STATE state = PyGILState_Ensure();
Py_AddPendingCall(&quit, NULL);
PyGILState_Release(state);
Esto debería ser suficiente para cualquier código de python puro. Pero tenga en cuenta que algunas funciones de C pueden ejecutarse por un tiempo como una sola operación (hubo un ejemplo con una búsqueda de expresiones regulares de larga ejecución, pero no estoy seguro de que aún sea relevante).