2009-05-31 9 views
13

Sto cercando un metodo in Ruby, che è fondamentalmente questo:Esiste un metodo semplice per verificare se un'istanza di Ruby IO bloccherà su read()?

io.ready_for_read? 

Voglio solo controllare se un determinato oggetto IO (nel mio caso, il risultato di una chiamata popen) è dotato di un'uscita a disposizione, vale a dire una chiamata di follow-up io.read(1) non bloccherà.

Queste sono le due opzioni che vedo, nessuno dei quali mi piace:

  1. io.read_nonblock - troppo sottile un'astrazione di Unix read() - Non voglio a che fare con errno gestione degli errori.

  2. io.select con timeout 0 - offusca lo scopo di questa semplice operazione.

C'è un'alternativa migliore che ho trascurato?

+0

Non lo so/penso/così. Questo è davvero ciò che la scelta è per. Sì, selezionare ha una sintassi orribile, ma immagino che in teoria potresti monkeypatch un "ready_for_read?" digitare il metodo in IO che utilizza select. –

+0

L'implementazione 'IO # ready_for_read?' Non funziona per me, restituisce sempre true. Penso che il problema sia che i blocchi 'IO # select' fino a quando il flusso non viene aperto per la scrittura da un altro processo (che nel mio caso lo è sempre), non finché non ci sono dati reali da leggere.Sto cercando di rintracciare un altro modo per raggiungere questo obiettivo, ma non ho molta fortuna. –

risposta

7

un po 'tardi, ma se si require 'io/wait', è possibile utilizzare ready? per verificare che il IO può essere letta senza bloccare. Certo, a seconda di quanto intendi leggere (e di come hai intenzione di farlo) il tuo oggetto IO può ancora bloccarsi, ma questo dovrebbe aiutare. Non sono sicuro che questa libreria sia supportata su tutte le piattaforme e inoltre non so perché questa funzionalità sia stata separata dal resto della libreria IO. Vedi di più qui: http://ruby-doc.org/stdlib/libdoc/io/wait/rdoc/

6

Sono pronto a concludere che no, non esiste un metodo semplice per farlo. Per suggerimento di Peter Cooper, ecco 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

Su Windows ho visto alcune incoerenze con IO/wait. Il rubino che ho qui in questo momento è:

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

Su questo sia nread e pronto? sono implementati, ma restituiscono risultati errati. Su una versione diversa che stavo usando pronto? era ancora rotto e nread non esisteva nemmeno.

Una possibilità è utilizzare io.stat.size, che indica il numero di byte disponibili per la lettura in un flusso IO.

La documentazione suggerisce che è per i file, ma l'ho usato su pipe collegate a un processo separato (tramite Open3.popen3 di Ruby). Ha funzionato per me finora.

+0

No-repro per STDIN. Legge zero anche se sicuramente ci sono dati da leggere. –

Problemi correlati