Python 在与 ruby 代码交互时从标准输入中读取挂起
Python reading from stdin hangs when interacting with ruby code
我试图将 python 和 ruby 代码放入对话中,我从这个 link (http://www.decalage.info/python/ruby_bridge)
中找到了方法
我试了最后一种方法,用stdin和stdout传递信息。我对原始代码进行了一些更改,使其适合 python 3.4,但我不确定我更改的代码是否将所有内容搞砸了。我的 python 程序在从 stdin 读取时总是挂起,并且没有打印任何内容。我不熟悉 stdin 和 stdout,所以我只是想知道为什么这不起作用。
这是我的 ruby 代码:
$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 异常手动中断进程之前,什么都没有显示。
我已经为这个问题苦苦挣扎了很长时间,我不知道出了什么问题......
提前感谢您提供的任何帮助!
不同之处在于 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")
().
我试图将 python 和 ruby 代码放入对话中,我从这个 link (http://www.decalage.info/python/ruby_bridge)
中找到了方法我试了最后一种方法,用stdin和stdout传递信息。我对原始代码进行了一些更改,使其适合 python 3.4,但我不确定我更改的代码是否将所有内容搞砸了。我的 python 程序在从 stdin 读取时总是挂起,并且没有打印任何内容。我不熟悉 stdin 和 stdout,所以我只是想知道为什么这不起作用。
这是我的 ruby 代码:
$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 异常手动中断进程之前,什么都没有显示。 我已经为这个问题苦苦挣扎了很长时间,我不知道出了什么问题...... 提前感谢您提供的任何帮助!
不同之处在于 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")
(