是否有一种简单的方法来检查 Ruby IO 实例是否会在 read() 上阻塞?

Posted

技术标签:

【中文标题】是否有一种简单的方法来检查 Ruby IO 实例是否会在 read() 上阻塞?【英文标题】:Is there a simple method for checking whether a Ruby IO instance will block on read()? 【发布时间】:2010-10-30 04:20:52 【问题描述】:

我正在寻找一种 Ruby 中的方法,基本上是这样的:

io.ready_for_read?

我只想检查给定的IO 对象(在我的情况下,是popen 调用的结果)是否有可用的输出,即后续调用io.read(1) 是否不会阻塞。

这是我看到的两个选项,我都不喜欢:

    io.read_nonblock - Unix 的抽象太薄了 read() - 我不想处理 errno 错误处理。

    io.select with timeout 0 -- 混淆了这个简单操作的目的。

有没有我忽略的更好的选择?

【问题讨论】:

我不/认为/这样。这确实是 select 的用途。是的,select 的语法很糟糕,但我想理论上你可以给“ready_for_read”打补丁?在使用 select 的 IO 中键入方法。 IO#ready_for_read? 的实现对我不起作用——它总是返回 true。我认为问题在于IO#select 阻塞,直到流被另一个进程打开写入(在我的情况下它总是已经如此),直到有实际数据要读取。我正在尝试寻找另一种方法来实现这一目标,但我运气不佳。 【参考方案1】:

在 Windows 上,我发现了一些与 IO/wait 不一致的地方。我现在这里的红宝石是:

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

在这一个上 nreadready? 都实现了,但它们返回错误的结果。在我使用的另一个版本上,ready? 仍然损坏,并且 nread 甚至都不存在。

一种可能性是使用 io.stat.size,它告诉您在 IO 流中可读取的字节数。 http://www.ruby-doc.org/core/classes/File/Stat.html

文档建议它用于文件,但我已在连接到单独进程的管道上使用它(通过 Ruby 的 Open3.popen3)。到目前为止它对我有用。

【讨论】:

STDIN 不可复制。即使肯定有要读取的数据,它也会读取为零。【参考方案2】:

有点晚了,不过如果你require 'io/wait',可以使用ready?来验证IO可以无阻塞读取。当然,取决于您打算阅读多少(以及您打算如何阅读),您的 IO 对象可能仍会阻塞,但这应该会有所帮助。我不确定这个库是否在所有平台上都受支持,我也不知道为什么这个功能与 IO 库的其余部分是分开的。在此处查看更多信息:http://ruby-doc.org/stdlib/libdoc/io/wait/rdoc/

【讨论】:

【参考方案3】:

我已经准备好得出结论,不,没有简单的方法可以做到这一点。根据 Peter Cooper 的建议,这里是IO#ready_for_read?

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

【讨论】:

以上是关于是否有一种简单的方法来检查 Ruby IO 实例是否会在 read() 上阻塞?的主要内容,如果未能解决你的问题,请参考以下文章

是否有一种简单的方法可以在 App Store 上检查用户的订阅状态,或者唯一的方法是进行收据和订阅验证?

在 Ruby on Rails 中测试模型实例是不是为“空”的最佳方法是啥?

如何检查特定属性是不是是有效的 ruby​​ on rails

是否有一种惯用的方式来操作 Ruby 中的 2 个数组?

从本地文件或 url 打开一个 IO 流

Python:检查范围内是不是存在对象[重复]