Sinatra 1.3 Streaming w/Ruby stdout 重定向 [英] Sinatra 1.3 Streaming w/ Ruby stdout redirection
问题描述
我想使用 1.3 中引入的 Sinatra 的 Streaming 功能以及一些 stdout 重定向.它基本上是一个长时间运行的工作的实时流输出.我查看了 this question 和自述文件中的 Sinatra 流示例.
I would like to use Sinatra's Streaming capability introduced in 1.3 coupled with some stdout redirection. It would basically be a live streaming output of a long running job. I looked into this question and the Sinatra streaming sample in the README.
在 OSX 上运行 1.8.7:
Running 1.8.7 on OSX:
require 'stringio'
require 'sinatra'
$stdout.sync = true
module Kernel
def capture_stdout
out = StringIO.new
$stdout = out
yield out
ensure
$stdout = STDOUT
end
end
get '/' do
stream do |out|
out << "Part one of a three part series... <br>\n"
sleep 1
out << "...part two... <br>\n"
sleep 1
out << "...and now the conclusion...\n"
Kernel.capture_stdout do |stream|
Thread.new do
until (line = stream.gets).nil? do
out << line
end
end
method_that_prints_text
end
end
end
def method_that_prints_text
puts "starting long running job..."
sleep 3
puts "almost there..."
sleep 3
puts "work complete!"
end
所以这段代码正确地打印出前三个字符串,并在 method_that_prints_text
执行时阻塞并且不向浏览器打印任何内容.我的感觉是 stdout 在第一次调用时是空的,它永远不会输出到输出缓冲区.我不太确定正确的顺序是什么,希望得到任何建议.
So this bit of code prints out the first three strings properly, and blocks while the method_that_prints_text
executes and does not print anything to the browser. My feeling is that stdout is empty on the first call and it never outputs to the out buffer. I'm not quite sure what the proper ordering would be and would appreciate any suggestions.
我尝试了上面问题中提到的一些 EventMachine 实现,但无法使它们工作.
I tried a few of the EventMachine implementations mentioned in the question above, but couldn't get them to work.
更新
我尝试了一些与在新线程中运行该方法的方法略有不同的方法,并按照 这里...
I tried something slightly different to where I had the method run in a new thread, and override STDOUT for that thread as described here...
而不是上面的 Kernel.capture_stdout
...
s = StringIO.new
Thread.start do
Thread.current[:stdout] = s
method_that_prints_text
end.join
while line = s.gets do
out << line
end
out << s.string
使用上面链接中列出的 ThreadOut
模块,这似乎工作得更好一些.但是它不会流式传输.唯一一次将某些内容打印到浏览器是在最后一行 out <<s.string
.StringIO
没有流式传输能力吗?
With the ThreadOut
module listed in the link above, this seems to work a bit better. However it doesn't stream. The only time something is printed to the browser is on the final line out << s.string
. Does StringIO
not have the capability to stream?
推荐答案
我最终解决了这个问题,发现 s.string
随着时间的推移会定期更新,所以我只是在一个单独的线程并抓住差异并将它们流式传输出来.似乎字符串重定向的行为不像普通的 IO 对象.
I ended up solving this by discovering that s.string
was updated periodically as time went on, so I just captured the output in a separate thread and grabbed the differences and streamed them out. It appears as though string redirection doesn't behave like a normal IO object.
s = StringIO.new
t = Thread.start do
Thread.current[:stdout] = s
method_that_prints_text
sleep 2
end
displayed_text = ''
while t.alive? do
current_text = s.string
unless (current_text.eql?(displayed_text))
new_text = current_text[displayed_text.length..current_text.length]
out << new_text
displayed_text = current_text * 1
end
sleep 2
end
这篇关于Sinatra 1.3 Streaming w/Ruby stdout 重定向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!