2009-07-26 11 views
7

considerar:Python: es os.read()/os.write() en un os.pipe() threadsafe?

pipe_read, pipe_write = os.pipe() 

Ahora, me gustaría saber dos cosas:

(1) Tengo dos hilos. Si garantizo que solo uno está leyendo os.read(pipe_read,n) y el otro solo está escribiendo os.write(pipe_write), ¿tendré algún problema, incluso si los dos hilos lo hacen simultáneamente? ¿Recibiré todos los datos escritos en el orden correcto? ¿Qué pasa si lo hacen simultáneamente? ¿Es posible que una sola escritura se lee en pedazos, como ?:

Thread 1: os.write(pipe_write, '1234567') 
Thread 2: os.read(pipe_read,big_number) --> '123' 
Thread 2: os.read(pipe_read,big_number) --> '4567' 

O - de nuevo, tenga en cuenta la simultaneidad - tendrá un solo os.write(some_string) siempre devolverá en su totalidad por un único os.read(pipe_read, very_big_number)?

(2) Considerar más de un hilo escrito al final pipe_write de la tubería usando logging.handlers.FileHandler() - He leído que el módulo de registro es multi-hilo. ¿Esto significa que puedo hacer esto sin perder datos? Creo que no podré controlar el orden de los datos en la tubería; pero esto no es un requisito. Requisitos:

  • todos los datos escritos por algunos hilos en el extremo de escritura deben salido al final leer
  • una cadena escrita por un solo logger.info(), logger.error(), ... tiene que permanecer en una sola pieza.

¿Se cumplen estos requisitos?

gracias de antemano,

Jan-Philip Gehrcke

+0

Por cierto: conozco 'Queue.Queue()' y 'select.select()'. En mi caso especial, la comunicación del Hilo A al Hilo B será a través de 'Queue.Queue()': transporta 'comandos'. Por el contrario, B-> A transportará mensajes de registro y se realizará a través de 'os.pipe()' como se describió anteriormente, porque el Tema A ya ha implementado un bucle de evento basado en 'select.select() ', que puede monitorear' pipe_read' e invocar una función de devolución de llamada si hay algo legible. –

Respuesta

8

os.read y os.write en los dos FDS regresaron de os.pipe es multi-hilo, pero se parece a exigir más que eso. Sub (1), sí, no hay garantía de "atomicidad" para las lecturas o escrituras de sinle: el escenario que representa (una sola escritura corta termina produciendo dos lecturas) es completamente posible. (En general, os.whatever es una envoltura delgada de la funcionalidad del sistema operativo, y le corresponde al sistema operativo asegurar o no garantizar el tipo de funcionalidad que necesita, en este caso, el estándar de Posix no requiere el sistema operativo para asegurar este tipo de "atomicidad"). Tiene la garantía de obtener todos los datos que se escribieron, y en el orden correcto, pero eso es todo. Una sola lectura de un pedazo grande de datos podría estancar una vez que se llena el buffer OS-suministrado y sólo procederá una vez que algún otro flujo ha leído algunos de los datos iniciales (cuidado con los puntos muertos, por supuesto!), Etc, etc.

Sub (2), sí, el módulo de registro es threadsafe Y "atómico" en los datos producidos por una sola llamada a logging.info, logging.warn, logging.error, etc., "se mantiene en una sola pieza" en términos de llamadas al subyacente manejador (sin embargo, si ese manejador a su vez utiliza medios no atómicos como os.write, aún puede, por ejemplo, bloquearse en el kernel hasta que el búfer subyacente se desatasque, etc., etc., como se indicó anteriormente).

+1

Muchas gracias por esta respuesta. "Se garantiza que obtendrás todos los datos que se escribieron, y en el orden correcto, pero eso es todo" -> Eso es todo lo que necesito, porque esto significa que puedo volver a ensamblar los datos recortados por un pequeño post-os.read () rutina de rutina Ahora puedo comenzar a programar con la conciencia tranquila. Gracias, de nuevo :-) –

+0

¡De nada! Puede usar un marcador distinguible al comienzo de cada 'escritura' para facilitar el proceso posterior de reensamblado. –

+0

Algunas actualizaciones: en realidad, tengo que usar el registro 'StreamHandler()' en lugar de 'FileHandler()'. Desde Python docs: El 'StreamHandler()' '' envía salida de [...] registro a cualquier objeto similar a un archivo (o, más precisamente, a cualquier objeto que admita los métodos 'write()' y 'flush()'). , Tengo que ajustar 'pipe_write' con' os.fdopen() ', para obtener los métodos de escritura y vaciado: ' logging.StreamHandler (os.fdopen (pipe_write, 'a', 0)) ' Espero que haya elegido buenas opciones sin búfer y modo de adición. –

Cuestiones relacionadas