【问题标题】:Embed Python CLI in a Ruby process?在 Ruby 进程中嵌入 Python CLI?
【发布时间】:2011-10-23 11:37:14
【问题描述】:

作为一个更大项目的一部分,我试图在 Ruby 进程中“嵌入”一个 Python 交互式解释器。我希望能够执行以下操作:

$ irb
irb(main):001:0> pipe = IO.popen("python", "w+")
=> #<IO:0x7f3dba4977e0>
irb(main):002:0> pipe.puts "print 'hello'"
=> nil
irb(main):003:0> pipe.gets
=> 'hello\n'

不幸的是,gets 似乎挂起,而不是从 Python 进程返回任何类型的输出。我用open3 尝试了这个过程的变体,使用模式r+ 而不是w+,以及其他几个小选项(其中python -u),但没有成功。

有没有办法通过 Ruby 与 Python shell 建立交互通信——实际上是“包装”Python CLI?我在 x86_64 机器上使用 Ruby 1.8.7(2010-06-23 补丁级别 299)和 Python 2.6.6,但希望解决方案可以跨 Python 版本移植(ish)。

【问题讨论】:

    标签: python ruby subprocess pipe interactive


    【解决方案1】:

    popen 看起来不像 python 的终端,所以你没有在交互模式下运行。您可以使用-i 强制 python 以交互模式启动:

    IO.popen("python -i", "r+") do |py|
      while cmd = gets
        py.puts cmd
        puts py.gets
      end
    end
    

    您可能需要做一些工作来删除&gt;&gt;&gt; 提示等。

    编辑:这里是多行友好的版本(我保持代码清晰并回答了原始问题):

    IO.popen("python -i", "r+") do |py|
      loop do
        fds = IO.select [py, STDIN]
        fds.each do |(fd)|
          case fd
          when nil;    next
          when STDIN;  py.puts gets
          else;        puts py.gets
          end
        end
      end
    end
    

    【讨论】:

    • 如果输出中有多行,这将无法正常工作。尝试运行 print 'line1\nline2'。它只返回第 1 行。
    【解决方案2】:

    这是使用 Ruby 的伪终端库的另一种方法。我已经在 Linux 和 MacOS X 上使用 ruby​​ 1.9 进行了测试,它可能无法在 Windows 上运行:

    require 'pty'
    
    begin
      # stty -echo turns off terminal echo, without it tty input would be repeated
      # on output
      PTY.spawn( "stty -echo; python" ) do |r, w, pid|
        begin
    
          cmd = nil
          begin
            w.puts cmd if cmd != nil
    
            # non-blocking read of stdout with 2 seconds timeout
            while IO.select([r], nil, nil, 2)
              print r.getc
            end
    
          end while cmd = gets
    
        rescue Errno::EIO
          puts "end of output"
        end
      end
    rescue PTY::ChildExited => e
      puts "The child process exited."
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-13
      相关资源
      最近更新 更多