2009-05-31 13 views
13

Busco un método en Ruby, que es básicamente el siguiente:¿Existe un método simple para verificar si una instancia de Ruby IO se bloqueará en read()?

io.ready_for_read? 

sólo quiero comprobar si un objeto dado IO (en mi caso, el resultado de una llamada popen) tiene salida disponible, es decir, una llamada de seguimiento io.read(1) no bloqueará.

Estas son las dos opciones que veo, ninguno de los cuales me gustan:

  1. io.read_nonblock - una abstracción demasiado delgada de Unix read() - Yo no quiero tratar con errno tratamiento de errores.

  2. io.select con tiempo de espera 0 - ofusca el propósito de esta operación simple.

¿Hay alguna alternativa mejor que he pasado por alto?

+0

No lo creo. Esto es realmente para lo que se selecciona. Sí, select tiene una sintaxis horrible, pero supongo que, en teoría, podrías poner en parche un "ready_for_read?" escriba el método en IO que usa seleccionar. –

+0

Esa implementación 'IO # ready_for_read?' No funciona para mí, siempre devuelve verdadero. Creo que el problema es que 'IO # select' bloquea hasta que la secuencia se abre para la escritura por otro proceso (que en mi caso siempre es así), no hasta que haya datos reales para leer.Estoy tratando de encontrar otra forma de lograr esto, pero no estoy teniendo mucha suerte. –

Respuesta

7

Un poco tarde, pero si require 'io/wait', puede utilizar ready? para verificar que la IO se puede leer sin bloquear. De acuerdo, dependiendo de cuánto pretendas leer (y cómo planeas hacerlo), tu objeto IO aún puede bloquearse, pero esto debería ser útil. No estoy seguro de si esta biblioteca es compatible con todas las plataformas, y tampoco sé por qué esta funcionalidad se separó del resto de la biblioteca de IO. Vea más aquí: http://ruby-doc.org/stdlib/libdoc/io/wait/rdoc/

6

Estoy listo para concluir que no, no hay un método simple para hacer esto. Por sugerencia de Peter Cooper, aquí es IO#ready_for_read?:

class IO 
    def ready_for_read? 
    result = IO.select([self], nil, nil, 0) 
    result && (result.first.first == self) 
    end 
end 
0

En Windows he visto algunas inconsistencias con IO/wait. El rubí que tengo aquí en este momento es:

rubí 1.9.2p136 (2010-12-25) [i386-mingw32]

En éste tanto nLea y listo? están implementados, pero devuelven resultados erróneos. En una versión diferente que estaba usando listo? todavía estaba roto y nread ni siquiera existía.

Una posibilidad es usar io.stat.size, que le indica la cantidad de bytes disponibles para leer en una secuencia IO. http://www.ruby-doc.org/core/classes/File/Stat.html

La documentación sugiere que es para archivos, pero lo he usado en tuberías conectadas a un proceso separado (a través de Open3 de Ruby). Hasta ahora me ha funcionado.

+0

No-repro para STDIN. Se lee cero aunque definitivamente hay datos para leer. –

Cuestiones relacionadas