首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >来自STDOUT的流式数据

来自STDOUT的流式数据
EN

Stack Overflow用户
提问于 2012-05-02 15:01:41
回答 1查看 2.5K关注 0票数 5

所以我有以下代码:

reader.rb

代码语言:javascript
复制
require 'open4'

def streamer(stdout)
  begin
    loop do
      data = stdout.read_nonblock(8)
      print data
    end
  rescue Errno::EAGAIN
    retry
  rescue EOFError
    puts 'End of file'
  end
end
pid, stdin, stdout, stderr = Open4::popen4 "ruby threader.rb"
stdout.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
streamer(stdout)

threader.rb

代码语言:javascript
复制
10.times do
  $stdout.puts "test"
  sleep 1
end

一个ruby脚本是一个简单的旋转器,它每秒都会输出到stdout。

另一个是用来运行该脚本的,我想捕获传入的数据。所以我想让流以非阻塞方式从stdout读取。

我似乎不能让它工作。我认为我正确地设置了fctnl O_NONBLOCK标志,但也许我没有。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-05-02 15:41:19

您的代码运行良好。您只遗漏了一件事,那就是刷新threader的输出缓冲区。

问题是STDOUT几乎总是被缓冲的,在这种情况下,除非被明确告知,否则不会刷新缓冲区,直到线程退出之后。

这就是为什么阅读器什么都看不到,然后当线程退出并且STDOUT被刷新时,它会突然得到一系列输出。

因此,这个测试的简单修复方法是:

代码语言:javascript
复制
10.times do
  $stdout.puts "test"
  $stdout.flush
  sleep 1
end

但是请注意,因为您正在使用NONBLOCK阅读,所以您的读者将忙于循环(!)消耗100% CPU。您真正应该做的是在读取之前等待传入的数据,以防止繁忙循环。

这可以使用IO.select来完成

代码语言:javascript
复制
...
loop do
  IO.select([stdout]) # <- waits for data (any data, even 1 byte)
  data = stdout.read_nonblock(8)
  print data
end  
...
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10409140

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档