在 python 中控制 ruby​​ 程序的标准输入和标准输出

Posted

技术标签:

【中文标题】在 python 中控制 ruby​​ 程序的标准输入和标准输出【英文标题】:control stdin and stdout of a ruby program in python 【发布时间】:2014-11-22 04:41:57 【问题描述】:

首先我应该注意到:我是一个 python 程序员,对 ruby​​ 一无所知!

现在,我需要输入一个 ruby​​ 程序的标准输入并使用以下命令捕获脚本的标准输出 一个python程序。 我尝试了this(第四个解决方案),代码在python2.7中有效,但在python3中无效; python3代码读取没有输出的输入。

现在,我需要一种方法将 ruby​​ 程序绑定到 python 2 或 3。

我的尝试:

此代码用六个模块编写,具有跨版本兼容性。

python 代码:

from subprocess import Popen, PIPE as pipe, STDOUT as out

import six

print('launching slave')
slave = Popen(['ruby', 'slave.rb'], stdin=pipe, stdout=pipe, stderr=out)

while True:
    if six.PY3:
        from sys import stderr
        line = input('enter command: ') + '\n'
        line = line.encode('ascii')
    else:
        line = raw_input('entercommand: ') + '\n'
    slave.stdin.write(line)
    res = []
    while True:
        if slave.poll() is not None:
            print('slave rerminated')
            exit()
        line = slave.stdout.readline().decode().rstrip()
        print('line:', line)
        if line == '[exit]': break
        res.append(line)
    print('results:')
    print('\n'.join(res))

红宝石代码:

while cmd = STDIN.gets
    cmd.chop!
    if cmd == "exit"
        break
    else
        print eval(cmd), "\n"
        print "[exit]\n"
        STDOUT.flush
    end
end

注意:

欢迎使用其他方式来做这些事情! (如socket编程等) 另外我认为不使用管道作为标准输出并使用类似文件的对象是一个更好的主意。 (如tempfileStringIO 等)

【问题讨论】:

【参考方案1】:

因为bufsize。在 Python 2.x 中,默认值为 0(无缓冲)。而在 Python 3.x 中,它更改为 -1(使用系统的默认缓冲区大小)。

明确指定它会解决您的问题。

slave = Popen(['ruby', 'slave.rb'], stdin=pipe, stdout=pipe, stderr=out, bufsize=0)

DEMO

【讨论】:

【参考方案2】:

下面是我如何使用 Ruby 和 Python3 的代码。

红宝石奴隶

# read command from standard input:
while cmd = STDIN.gets
  # remove whitespaces:
  cmd.chop!
  # if command is "exit", terminate:
  if cmd == "exit"
    break
  else
    # else evaluate command, send result to standard output:
    print eval(cmd), "\n"
    print "[exit]\n"
    # flush stdout to avoid buffering issues:
    STDOUT.flush
  end
end

Python 大师

from subprocess import Popen, PIPE as pipe, STDOUT as out

print('Launching slave')
slave = Popen(['ruby', 'slave.rb'], stdin=pipe, stdout=pipe, stderr=out, bufsize=0)

while True:
    from sys import stderr
    line = input('Enter command: ') + '\n'
    line = line.encode('ascii')
    slave.stdin.write(line)
    res = []
    while True:
        if slave.poll() is not None:
            print('Slave terminated')
            exit()
        line = slave.stdout.readline().decode().rstrip()
        if line == '[exit]': break
        res.append(line)
    print('results:')
    print('\n'.join(res))

【讨论】:

以上是关于在 python 中控制 ruby​​ 程序的标准输入和标准输出的主要内容,如果未能解决你的问题,请参考以下文章

Ruby RubyGems

Ruby RubyGems

从ruby调用和控制gdb

如何使用标准输入和标准输出在 C# 和 ruby​​ 进程之间进行通信

在 iPhone OS 应用程序中使用 Ruby/Python 代码?

在Rails应用程序中启动Ruby Gem版本控制