在与ruby代码交互时,从stdin读取的Python会挂起

时间:2015-06-28 20:37:02

标签: python ruby encoding stdio

我试图将python和ruby代码放入对话中,我从这个链接找到了方法(http://www.decalage.info/python/ruby_bridge

我尝试了最后一个方法,使用stdin和stdout传递信息。我对原始代码进行了一些更改,以便它适合python 3.4,但我不确定我改变的代码是否搞砸了所有的东西。从stdin读取时,我的python程序总是挂起,没有打印出来。我不熟悉stdin和stdout,所以我只是想知道为什么这不起作用。

以下是我的红宝石代码:

$stdin.set_encoding("utf-8:utf-8")
$stdout.set_encoding("utf-8:utf-8")

while cmd = $stdin.gets

    cmd.chop!
    if cmd == "exit"
        break
    else
        puts eval(cmd)
        puts "[end]"
        $stdout.flush

    end
end

我不确定是否可以像这样设置内部编码和外部编码。这是我的python代码:

from subprocess import Popen, PIPE, STDOUT

print("Launch slave process...")
slave = Popen(['ruby', 'slave.rb'], stdin=PIPE, stdout=PIPE, stderr=STDOUT)

while True:
    line = input("Enter expression or exit:")
    slave.stdin.write((line+'\n').encode('UTF-8'))
    result = []
    while True:
        if slave.poll() is not None:
            print("Slave has terminated.")
            exit()

        line = slave.stdout.readline().decode('UTF-8').rstrip()
        if line == "[end]":
            break
        result.append(line)
    print("result:")
    print("\n".join(result))

当我尝试运行python脚本时,输入" 3 * 4",然后按回车键,直到我用退出代码1和KeyboardInterrupt Exception手动中断进程才会显示任何内容。 我一直在努力解决这个问题很长一段时间,我不知道出了什么问题...... 提前感谢任何潜在的帮助!

1 个答案:

答案 0 :(得分:2)

不同之处在于Python 3.4中默认为bufsize=-1,因此slave.stdin.write()不会立即将行发送到ruby子进程。快速解决方法是添加slave.stdin.flush()电话。

#!/usr/bin/env python3
from subprocess import Popen, PIPE

log = print
log("Launch slave process...")
with Popen(['ruby', 'slave.rb'], stdin=PIPE, stdout=PIPE, 
           bufsize=1, universal_newlines=True) as ruby:
    while True:
        line = input("Enter expression or exit:")
        # send request
        print(line, file=ruby.stdin, flush=True)
        # read reply
        result = []
        for line in ruby.stdout:
            line = line.rstrip('\n')
            if line == "[end]":
                break
            result.append(line)
        else: # no break, EOF
            log("Slave has terminated.")
            break
        log("result:" + "\n".join(result))

它使用universal_newlines=True启用文本模式。它使用locale.getpreferredencoding(False)来解码字节。如果您想强制utf-8编码而不考虑区域设置,请删除universal_newlines并将管道包装到io.TextIOWrapper(encoding="utf-8")code example -- it also shows the proper exception handling for the pipes)。