我假设您使用
pty
是出于
Q:为什么不只使用管道(popen())?中概述的原因(到目前为止,所有其他答案都忽略了您的
“注意:我不想一次打印出所有内容”)。
如
在文档中所说,
pty
仅适用于Linux:
由于伪终端处理高度依赖于平台,因此只有针对Linux的代码才能进行处理。(Linux代码应该可以在其他平台上运行,但尚未经过测试。)
它在其他操作系统上的效果尚不清楚。
您可以尝试使用
pexpect
:
import sys
import pexpect
pexpect.run("ruby ruby_sleep.rb", logfile=sys.stdout)
或者使用
stdbuf
在非交互模式下启用行缓冲:
from subprocess import Popen, PIPE, STDOUT
proc = Popen(['stdbuf', '-oL', 'ruby', 'ruby_sleep.rb'],
bufsize=1, stdout=PIPE, stderr=STDOUT, close_fds=True)
for line in iter(proc.stdout.readline, b''):
print line,
proc.stdout.close()
proc.wait()
或者根据@Antti Haapala的答案,使用stdlib中的pty
:
import errno
import os
import pty
from subprocess import Popen, STDOUT
master_fd, slave_fd = pty.openpty()
proc = Popen(['ruby', 'ruby_sleep.rb'],
stdin=slave_fd, stdout=slave_fd, stderr=STDOUT, close_fds=True)
os.close(slave_fd)
try:
while 1:
try:
data = os.read(master_fd, 512)
except OSError as e:
if e.errno != errno.EIO:
raise
break
else:
if not data:
break
print('got ' + repr(data))
finally:
os.close(master_fd)
if proc.poll() is None:
proc.kill()
proc.wait()
print("This is reached!")
所有三个代码示例都会立即打印“hello”(一旦看到第一个EOL)。
保留旧的更复杂的代码示例,因为它可能会在SO上的其他帖子中被引用和讨论
或者使用基于@Antti Haapala的回答的pty
:
import os
import pty
import select
from subprocess import Popen, STDOUT
master_fd, slave_fd = pty.openpty()
proc = Popen(['ruby', 'ruby_sleep.rb'],
stdout=slave_fd, stderr=STDOUT, close_fds=True)
timeout = .04
while 1:
ready, _, _ = select.select([master_fd], [], [], timeout)
if ready:
data = os.read(master_fd, 512)
if not data:
break
print("got " + repr(data))
elif proc.poll() is not None:
assert not select.select([master_fd], [], [], 0)[0]
break
os.close(slave_fd)
os.close(master_fd)
proc.wait()
print("This is reached!")
if
应该缩进,使其位于循环内部。 - cdarke