<p>我假设您使用<code>pty</code>是由于<a href="http://pexpect.readthedocs.org/en/latest/FAQ.html#whynotpipe" rel="noreferrer">Q: Why not just use a pipe (popen())?</a>中列出的原因(到目前为止,所有其他答案都忽略了您的<em>“注意:我不想一次打印所有内容”</em>)。</p>
<p><code>pty</code>仅限Linux <a href="http://docs.python.org/dev/library/pty.html" rel="noreferrer">as said in the docs</a>:</p>
<blockquote>
<p>Because pseudo-terminal handling is highly platform dependent, there
is code to do it only for Linux. (The Linux code is supposed to work
on other platforms, but hasn’t been tested yet.)</p>
</blockquote>
<p>目前尚不清楚它在其他操作系统上的工作情况。</p>
<p>您可以尝试<code>pexpect</code>:</p>
<pre><code>import sys
import pexpect
pexpect.run("ruby ruby_sleep.rb", logfile=sys.stdout)
</code></pre>
<p>或者<a href="http://www.gnu.org/software/coreutils/manual/html_node/stdbuf-invocation.html#stdbuf-invocation" rel="noreferrer">^{<cd4>}</a>在非交互模式下启用行缓冲:</p>
<pre><code>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()
</code></pre>
<p>或者基于<a href="https://stackoverflow.com/a/28925318/4279">@Antti Haapala's answer</a>使用stdlib中的<code>pty</code>:</p>
<pre><code>#!/usr/bin/env python
import errno
import os
import pty
from subprocess import Popen, STDOUT
master_fd, slave_fd = pty.openpty() # provide tty to enable
# line-buffering on ruby's side
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 # EIO means EOF on some systems
else:
if not data: # EOF
break
print('got ' + repr(data))
finally:
os.close(master_fd)
if proc.poll() is None:
proc.kill()
proc.wait()
print("This is reached!")
</code></pre>
<p>这三个代码示例都会立即打印“hello”(只要看到第一个EOL)。</p>
<hr/>
<p><sup>把旧的更复杂的代码示例留在这里,因为它可能会在其他文章中被引用和讨论</p>
<p>或者基于<a href="https://stackoverflow.com/a/12225379/4279">@Antti Haapala's answer</a>使用<code>pty</code>:</p>
<pre><code>import os
import pty
import select
from subprocess import Popen, STDOUT
master_fd, slave_fd = pty.openpty() # provide tty to enable
# line-buffering on ruby's side
proc = Popen(['ruby', 'ruby_sleep.rb'],
stdout=slave_fd, stderr=STDOUT, close_fds=True)
timeout = .04 # seconds
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: # select timeout
assert not select.select([master_fd], [], [], 0)[0] # detect race condition
break # proc exited
os.close(slave_fd) # can't do it sooner: it leads to errno.EIO error
os.close(master_fd)
proc.wait()
print("This is reached!")
</code></pre>