Python sys.stdin.read (max) bloquea hasta que se lee max (si max> = 0), bloquea hasta EOF, pero la selección indica que hay datos para leer

Mi problema es:

select indica que hay datos para leer, quiero leer lo que esté allí, no quiero esperar a que esté presente una cantidad max . si max <= 0, entonces la lectura espera hasta que se encuentre EOF, si max > 0 lee los bloques hasta que se puedan leer los bytes max .

No quiero esto, quiero leer lo que sea que haya hecho, póngalo en la lista “listo para leer”. leer (1) no es práctico porque implicará MUCHAS llamadas para leer. PERO no debe bloquear.

¿Hay alguna forma de averiguar la cantidad presente en el búfer cuando los retornos seleccionados (si se devuelve indicando que se puede leer algo, en lugar de agotarse) y leer esa cantidad? ¿Hay una manera de usar max como se haría con sockets? ¿Dónde se lee todo lo que puede al instante, y luego vuelve?

¿Una solución podría ser poner el archivo en modo de no locking para la lectura? No estoy seguro, no esperaba este comportamiento “hasta EOF”.

Seguiré leyendo e intentando, pero solo he pasado 30 minutos más o menos y no me he acercado más, por eso te apelo.

NOTA

Hay muchas preguntas que preguntan cómo hacer una espera para una cantidad de entrada, y hacer que las cosas se bloqueen hasta que llegue ese máximo, no estoy buscando esto. Mi problema es que está bloqueando.

Apéndice

setblocking(False) no funcionó, ahora estoy leyendo sobre cómo hacer que no se bloquee durante la lectura. Me da esperanza la documentación:

 stdin.read Found at: sys read([size]) -> read at most size bytes, returned as a string. If the size argument is negative or omitted, read until EOF is reached. Notice that when in non-blocking mode, less data than what was requested may be returned, even if no size parameter was given. 

Addendum II

Parece que leer (0) en realidad lee 0, eso no es nada, esto resulta en un bucle sin fin, ¡lo que es interesante!

Lo siento, en realidad no probé el 0, parece que empecé con 4096 (pensando que leerá lo que sea que esté allí …) Probé sin parámetros, pero no con 0.

Me pregunto qué uso sería leer (0)?

Addendum III

Ahora estoy teniendo problemas con select (he intentado tomar read (1) como solución) Aquí está el código real:

 def getInput(self): log.log(log.INFO,"GetInput","Select") readsReady = select.select((sys.stdin,),(),(),1)[0] if len(readsReady) == 0: #timed out log.log(log.INFO,"GetInput","Select timed out") if not self.toClose: self.handler.post("GetInput") else: threads.getCurrentThread().removeAllHandlers() else: #OPTIMISED FOR READING 1 #log.log(log.INFO,"GetInput","Reading") data = sys.stdin.read(1) log.log(log.INFO,"GetInput","Read: "+data) if data == "\n": self.onInputHandler.post("OnInput",self.buffer) self.buffer="" else: self.buffer+=data self.handler.post("GetInput") 

Hay algunas cosas en la siguiente salida no relacionadas con esto, son el “¡Hola mundo!” Eso llega casi al instante, y la “PRUEBA!” Aproximadamente 5 segundos. El “hola” es algo que escribí, la entrada, la “k” es algo que escribí más tarde, después de escribir ambos presiono Intro una vez.

Salida:

 0.0147 Verbose 1 SocketReader Created reader 0.0156 Verbose 2 SocketWriter Created writer 0.0260 Information 0 SocketReadWriter Created and ready for: ('localhost', 8294) 0.0268 Information 3 GetInput Select Hello World! 1.0281 Information 3 GetInput Select timed out 1.0584 Information 3 GetInput Select 2.0593 Information 3 GetInput Select timed out 2.0896 Information 3 GetInput Select 3.0900 Information 3 GetInput Select timed out 3.1203 Information 3 GetInput Select 4.1215 Information 3 GetInput Select timed out 4.1519 Information 3 GetInput Select TEST! 5.1524 Information 3 GetInput Select timed out 5.1828 Information 3 GetInput Select hello 6.1467 Information 3 GetInput Read: h 6.1770 Information 3 GetInput Select 7.1782 Information 3 GetInput Select timed out 7.2086 Information 3 GetInput Select 8.2098 Information 3 GetInput Select timed out 8.2401 Information 3 GetInput Select 9.2414 Information 3 GetInput Select timed out 9.2717 Information 3 GetInput Select 10.2723 Information 3 GetInput Select timed out 10.3026 Information 3 GetInput Select k 10.7939 Information 3 GetInput Read: e 10.8243 Information 3 GetInput Select 10.8245 Information 3 GetInput Read: l 10.8547 Information 3 GetInput Select 10.8549 Information 3 GetInput Read: l 10.8851 Information 3 GetInput Select 10.8853 Information 3 GetInput Read: o 10.9155 Information 3 GetInput Select 10.9157 Information 3 GetInput Read: 10.9459 Information 3 GetInput Select 10.9461 Information 3 GetInput Read: k 10.9763 Information 3 GetInput Select You said: hello 11.9775 Information 3 GetInput Select timed out 12.0123 Information 3 GetInput Select 13.0133 Information 3 GetInput Select timed out 13.0437 Information 3 GetInput Select ^C13.3985 Verbose 2 Threads Thread: 2 has ended 14.0442 Information 3 GetInput Select timed out 14.0746 Information 3 GetInput Select 14.3622 Verbose 1 Threads Thread: 1 has ended 15.0758 Information 3 GetInput Select timed out 15.1363 Information 3 GetInput Select 16.1373 Information 3 GetInput Select timed out 16.1677 Verbose 3 Threads Thread: 3 has ended 

Esto es más fácil de ver aquí: http://pastebin.com/raw.php?i=H6UHHmy8

¿Qué es raro?

Lee la “h” de hola, pero no lee el “hola \ n” hasta que sucede k, siempre hay 1 letra por delante de 1 nueva línea por detrás si eso tiene sentido.

¿Las múltiples llamadas a seleccionar causarán un problema? (en otro hilo el lector socket también usa seleccionar)

El formato para el registro es:

* Tiempo desde el inicio del progtwig.

*Nivel de registro

* ID de hilo (Único entre hilos en ejecución)

* Etiqueta de registro

* Mensaje de registro

Lo que hace la clase Handler

Al permitir que los subprocesos envíen mensajes de forma segura entre sí, el controlador comprueba una cola (y cualquier evento reservado suceda en un momento determinado, como el TEST, que ocurre en un subproceso diferente, no se preocupe), la publicación de “GetInput” progtwig otra llamada a GetInput, colocándola al final de la cola. El mensaje “OnInput” se pasa al controlador de un subproceso diferente, el que quiero tratar con la entrada.

Lo he hecho de esta manera porque proporciona una buena forma de manejar el subprocesamiento, y significa que tengo un código reutilizable (como el SocketReadWriter). Espero que esto no resulte en una crítica de mi modelo de subprocesos, pero en realidad funciona. . El problema es con mi bash de obtener la entrada del usuario.

También puedes ver cuando hago ctrl + c que la cosa se apaga, esto es lo que hace la cosa toClose. Cuando se selecciona el tiempo de espera, si se supone que se cierra, lo hará. Un hilo finaliza cuando ya no le quedan controladores (los controladores solo toman el control después de que la función que el hilo debe ejecutar ha regresado, esta función puede crear una clase que tiene un controlador para un miembro, por lo tanto, cuando el constructor regresa y la función regresa , hay un manejador manteniendo viva la clase)

Trabajar alrededor

 def getInput(self): log.log(log.INFO,"GetInput","Select") if sys.stdin.closed: readsReady = [] else: readsReady = select.select((sys.stdin,),(),(),1)[0] if len(readsReady) == 0: #timed out log.log(log.INFO,"GetInput","Select timed out") if not self.toClose: self.handler.post("GetInput") else: threads.getCurrentThread().removeAllHandlers() else: data = sys.stdin.readline() if len(data) == 0: log.log(log.WARN,"GetInput","No data was returned indicating the file was closed") self.handler.post("GetInput") #if this is a close event, the next #timeout will deal with it return if data[-1] == "\n": data = data[:-1] log.log(log.INFO,"GetInput","Read: "+data) self.onInputHandler.post("OnInput",data) #if data == "\n": # self.onInputHandler.post("OnInput",self.buffer) # self.buffer="" #else: # self.buffer+=data self.handler.post("GetInput") def onClose(self): #log.log(log.WARN,"Input: OnClose","Called") self.toClose = True sys.stdin.close() 

En el módulo os hay os.read función os.read que permite un control de nivel inferior sobre la lectura del descriptor de archivos. Es sin locking siempre que haya al menos un byte listo para leer.

 os.read(fd, n) 

Lea a lo sumo n bytes del descriptor de archivos fd. Devuelve una cadena que contiene los bytes leídos. Si se ha llegado al final del archivo al que hace referencia fd, se devuelve una cadena vacía.

Disponibilidad: Unix, Windows.

Nota: esta función está diseñada para E / S de bajo nivel y debe aplicarse a un descriptor de archivos tal como lo devuelve os.open() o pipe() . Para leer un “objeto de archivo” devuelto por la función integrada open() o por popen() o fdopen() , o sys.stdin , use sus métodos read() o readline() .