Q:パイプ(popen())だけを使用pty
しないのはなぜですか?(これまでの他のすべての回答は、 「注:すべてを一度に印刷したくない」を無視します)。
pty
ドキュメントで述べられているようにLinuxのみです:
疑似端末の処理はプラットフォームに大きく依存するため、Linuxでのみ処理するコードがあります。(Linuxコードは他のプラットフォームで動作するはずですが、まだテストされていません。)
他のOSでどれだけうまく機能するかは不明です。
あなたは試すことができます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の回答pty
に基づいてstdlibから使用します:
#!/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!")
3つのコード例はすべて、すぐに「hello」を出力します(最初のEOLが表示されるとすぐに)。
SOの他の投稿で参照および説明されている可能性があるため、古いより複雑なコード例をここに残します
または@AnttiHaapalaの回答pty
に基づいて使用します:
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!")