【问题标题】:Python reading from stdin hangs when interacting with ruby code与 ruby​​ 代码交互时,从 stdin 读取的 Python 挂起
【发布时间】:2015-06-28 20:37:01
【问题描述】:

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

我尝试了最后一种方法,使用标准输入和标准输出来传递信息。我对原始代码进行了一些更改,使其适合 python 3.4,但我不确定我更改的代码是否把所有事情都搞砸了。从标准输入读取时,我的 python 程序总是挂起,并且没有打印任何内容。我不熟悉标准输入和标准输出,所以我只是想知道为什么这不起作用。

这是我的红宝石代码:

$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 手动中断进程之前,什么都没有显示。 我已经为这个问题苦苦挣扎了很长时间,我不知道出了什么问题...... 提前感谢您的任何潜在帮助!

【问题讨论】:

    标签: python ruby encoding stdio


    【解决方案1】:

    不同之处在于bufsize=-1 默认在 Python 3.4 中,因此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)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-18
      • 2011-01-28
      • 2011-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多