gpt4 book ai didi

ruby open3 stdout 和 stdin 如何交互

转载 作者:行者123 更新时间:2023-12-03 17:38:17 29 4
gpt4 key购买 nike

sum.rb很简单。您输入两个数字,它返回总和。

# sum.rb
puts "Enter number A"
a = gets.chomp
puts "Enter number B"
b = gets.chomp
puts "sum is #{a.to_i + b.to_i}"
robot.rb二手 Open3.popen3sum.rb 互动.这是代码:
# robot.rb
require 'open3'

Open3.popen3('ruby sum.rb') do |stdin, stdout, stderr, wait_thr|
while line = stdout.gets
if line == "Enter number A\n"
stdin.write("10\n")
elsif line == "Enter number B\n"
stdin.write("30\n")
else
puts line
end
end
end
robot.rb无法运行。好像卡在 sum.rbgets.chomp .

后来我发现我必须写如下才能使它工作。您需要事先以正确的顺序为它提供输入。
# robot_2.rb
require 'open3'

Open3.popen3('ruby sum.rb') do |stdin, stdout, stderr, wait_thr|
stdin.write("10\n")
stdin.write("30\n")
puts stdout.read
end

让我困惑的是:
  • robot_2.rb不像与 shell 交互 ,更像是喂 shell 需要什么,因为我只知道 .如果一个程序需要很多输入而我们无法预测顺序怎么办?
  • 我发现如果 STDOUT.flush在每个 puts 之后添加在 sum.rb , robot.rb可以运行。但实际上我们不能相信sum.rb的作者可以添加 STDOUT.flush , 对?

  • 谢谢你的时间!

    最佳答案

    终于想出了如何做到这一点。使用 write_nonblockreadpartial .你必须小心的是stdout.readpartial完全按照它说的去做,这意味着您将不得不聚合数据并执行 gets自己寻找换行符。

    require 'open3'
    env = {"FOO"=>"BAR", "BAZ"=>nil}
    options = {}
    Open3.popen3(env, "cat", **options) {|stdin, stdout, stderr, wait_thr|
    stdin.write_nonblock("hello")

    puts stdout.readpartial(4096)
    # the magic 4096 is just a size of memory from this example:
    # https://apidock.com/ruby/IO/readpartial


    stdin.close
    stdout.close
    stderr.close
    wait_thr.join
    }

    对于正在寻找更通用交互性(例如 ssh 交互)的人,您可能希望创建单独的线程来聚合标准输出和触发标准输入。
    require 'open3'
    env = {"FOO"=>"BAR", "BAZ"=>nil}
    options = {}
    unprocessed_output = ""
    Open3.popen3(env, "cat", **options) {|stdin, stdout, stderr, wait_thr|

    on_newline = ->(new_line) do
    puts "process said: #{new_line}"
    # close after a particular line
    stdin.close
    stdout.close
    stderr.close
    end

    Thread.new do
    while not stdout.closed? # FYI this check is probably close to useless/bad
    unprocessed_output += stdout.readpartial(4096)
    if unprocessed_output =~ /(.+)\n/
    # extract the line
    new_line = $1
    # remove the line from unprocessed_output
    unprocessed_output.sub!(/(.+)\n/,"")
    # run the on_newline
    on_newline[new_line]
    end

    # in theres no newline, this process will hang forever
    # (e.g. probably want to add a timeout)
    end
    end

    stdin.write_nonblock("hello\n")

    wait_thr.join
    }

    顺便说一句,这不是线程安全的。这只是我发现的一个未优化但功能强大的解决方案,希望将来会得到改进。

    关于ruby open3 stdout 和 stdin 如何交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43026405/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com