2012-02-07 7 views
5

Estamos desarrollando una pequeña aplicación de servidor c. La aplicación del servidor procesa algunos datos y responde al cliente. Para mantener la parte de procesamiento de datos configurable y flexible, decidimos ir a las secuencias de comandos y, en función de la disponibilidad de varios módulos listos, decidimos apostar por Python. Estamos utilizando la API de Python-C para enviar/recibir datos entre c y python.Python-C api concurrence issue

El algoritmo funciona algo como esto: -

  1. Server recibe algunos datos de cliente, estos datos se almacenan en un diccionario creado en c. El diccionario se crea usando la función api PyDict_New(); desde C. La entrada se almacena como un par de valores clave en el diccionario utilizando la función api PyDict_SetItemString();
  2. A continuación, ejecutamos el script python PyRun_SimpleString(); pasando la secuencia de comandos como un parámetro. Este script hace uso del diccionario creado en c. Tenga en cuenta que hacemos que el diccionario creado en c, accesible para el script, utilice los métodos PyImport_AddModule(); y PyModule_AddObject();
  3. Almacenamos el resultado del procesamiento de datos en el script como un par de valores clave en el mismo diccionario creado anteriormente. El código c simplemente puede acceder a la variable de resultado (par clave-valor) después de que se haya ejecutado el script.

El problema El problema que enfrentamos es en el caso de solicitudes simultáneas que vienen de diferentes clientes. Cuando llegan varias solicitudes de diferentes clientes, tendemos a objetar excepciones de recuento de referencias. Tenga en cuenta que, para cada solicitud que entra para un usuario, creamos un diccionario independiente solo para ese usuario. Para superar este problema, abarcamos la llamada a PyRun_SimpleString(); dentro de PyEval_AcquireLock(); y PyEval_ReleaseLock() ;, pero al hacer esto, la ejecución del script es una llamada de bloqueo. Entonces, si un script tarda mucho tiempo en ejecutarse, todos los demás usuarios también están esperando una respuesta.

Podría por favor sugerir el mejor enfoque posible o dar punteros a donde estamos yendo mal. Por favor, hazme ping para más información.

Cualquier ayuda/guía será apreciada.

Respuesta

1

Quizás se esté perdiendo una de las llamadas mencionadas en this answer.

+0

Gracias por la referencia Jane. Por cierto, hice llamadas a esas funciones, pero aún no funciona. – Will

1

Probablemente deberías leer http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock Tu problema se explica en el primer párrafo.

Cuando adquiere el GIL, hágalo alrededor de su manipulación directa de objetos Python. La llamada a PyRun_SimpleString manejará el GIL internamente y lo abandonará en operaciones de larga ejecución o simplemente en cada X instrucciones. SIN EMBARGO, NO SERÁ verdaderamente multihilo.

Editar:

Es necesario adquirir la cerradura y hay que asegurarse de que Python sabe que está en un estado de subproceso diferente:

// acquire the lock and switch thread state 
PyEval_AcquireLock(); 
PyThreadState_Swap(perThreadState); 

// execute some python code 
PyEval_SimpleString("print 123"); 

// clear the thread state and release the lock 
PyThreadState_Swap(NULL); 
PyEval_ReleaseLock(); 
+0

Hola Tom, gracias por la respuesta. ¿Podrían explicar el hecho de que "NO" será verdaderamente multihilo?¿Quiere decir que los scripts nunca se pueden ejecutar en paralelo? – Will

+0

Hay un bloqueo de intérprete global: solo se ejecutará una instrucción de bytecode de python en cualquier momento, independientemente de la cantidad de subprocesos que haya. Las funciones de ejecución prolongada, como el archivo abierto, liberan el bloqueo temporalmente mientras se están ejecutando, y el intérprete de Python abandona periódicamente el bloqueo, pero, en última instancia, dentro de un proceso, los códigos de byte de Python se ejecutan en serie. –

+0

Gracias por eso Tom. Aprecie su tiempo por las respuestas. Confirme esto: si PyRun_SimpleString se está ejecutando en 2 (o quizás n) hilos "c" separados, se ocupa del GIL mismo y, por lo tanto, no es necesario bloquearlo o bloquearlo antes de realizar una llamada a PyRun_SimpleString desde cualquier hilo. – Will

1

le sugiero que investigue el módulo multiprocessing.