2009-05-31 3 views
13

Je suis à la recherche d'une méthode en Ruby qui est essentiellement ceci:Existe-t-il une méthode simple pour vérifier si une instance Ruby IO se bloquera sur read()?

io.ready_for_read? 

Je veux juste vérifier si un objet IO donné (dans mon cas, le résultat d'un appel popen) a sortie disponible, à savoir un appel de suivi io.read(1) ne bloquera pas.

Ce sont les deux options que je vois, ni dont j'aime:

  1. io.read_nonblock - une abstraction d'Unix read() trop mince - Je ne veux pas traiter errno la gestion des erreurs.

  2. io.select avec le délai 0 - obscurcit le but de cette opération simple.

Y a-t-il une meilleure alternative que j'ai oubliée?

+0

Je ne fais pas/pense/ainsi. C'est vraiment ce que le choix est pour. Oui, select a une syntaxe horrible, mais je suppose qu'en théorie vous pouvez choisir un "ready_for_read?" tapez la méthode dans IO qui utilise select. –

+0

Cette implémentation 'IO # ready_for_read?' Ne fonctionne pas pour moi - elle retourne toujours vrai. Je pense que le problème est que "IO # select" bloque jusqu'à ce que le flux soit ouvert pour l'écriture par un autre processus (ce qui est toujours le cas dans mon cas), pas avant qu'il y ait des données à lire.J'essaie de trouver un autre moyen d'y parvenir, mais je n'ai pas beaucoup de chance. –

Répondre

7

Un peu en retard, mais si vous require 'io/wait', vous pouvez utiliser ready? pour vérifier que l'IO peut être lu sans bloquer. Accordé, en fonction de combien vous avez l'intention de lire (et comment vous prévoyez de le faire) votre objet IO peut encore bloquer, mais cela devrait aider. Je ne suis pas sûr que cette bibliothèque soit supportée sur toutes les plateformes, et je ne sais pas non plus pourquoi cette fonctionnalité a été séparée du reste de la bibliothèque IO. Voir plus ici: http://ruby-doc.org/stdlib/libdoc/io/wait/rdoc/

6

Je suis prêt à conclure que non, il n'y a pas de méthode simple pour le faire. Par la suggestion de Peter Cooper, voici 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

Sur Windows j'ai vu quelques incohérences avec IO/wait. Le rubis que j'ai ici droit est maintenant:

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

Sur celui-ci à la fois NREAD et prêt? sont implémentés, mais ils retournent des résultats erronés. Sur une version différente que j'utilisais prêt? était encore cassé et nread n'existait même pas.

Une possibilité est d'utiliser io.stat.size, qui indique le nombre d'octets disponibles pour la lecture dans un flux d'E/S. La documentation suggère que c'est pour les fichiers, mais je l'ai utilisé sur des tuyaux connectés à un processus séparé (via Open3.popen3 de Ruby). Cela a fonctionné pour moi jusqu'à présent.

+0

Pas de repro pour STDIN. Il lit zéro même s'il y a définitivement des données à lire. –

Questions connexes