Python子进程readlines()挂起
我尝试完成的任务是流式处理ruby文件并打印输出。(注意:我不想一次打印出所有内容)
main.py
from subprocess import Popen, PIPE, STDOUTimport pty
import os
file_path = '/Users/luciano/Desktop/ruby_sleep.rb'
command = ' '.join(["ruby", file_path])
master, slave = pty.openpty()
proc = Popen(command, bufsize=0, shell=True, stdout=slave, stderr=slave, close_fds=True)
stdout = os.fdopen(master, 'r', 0)
while proc.poll() is None:
data = stdout.readline()
if data != "":
print(data)
else:
break
print("This is never reached!")
ruby_sleep.rb
sleep 2puts "goodbye!"
问题
流文件工作正常。打招呼/再见输出将延迟2秒打印。就像脚本应该工作一样。问题是readline()最终挂起并且永不退出。我从来没有达到最后的打印。
我知道这里有很多类似的问题,但是这些都不是让我解决问题的方法。我并不是整个子流程中的人,所以请给我一个更实际的/具体的答案。
问候
编辑
修复意外的代码。(与实际错误无关)
回答:
我假设你pty是出于Q中概述的原因而使用的:为什么不仅仅使用管道(popen())?(到目前为止,所有其他答案都将忽略你的“注意:我不想一次打印所有内容”)。
pty仅在docs中说过是Linux :
由于伪终端处理高度依赖平台,因此有代码仅适用于Linux
。(Linux代码应该可以在其他平台上运行,但尚未经过测试。)
目前尚不清楚它在其他操作系统上的运行情况。
你可以尝试pexpect:
import sysimport pexpect
pexpect.run("ruby ruby_sleep.rb", logfile=sys.stdout)
或stdbuf在非交互模式下启用行缓冲:
from subprocess import Popen, PIPE, STDOUTproc = 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()
或者pty基于@Antti Haapala的答案从stdlib 使用:
#!/usr/bin/env pythonimport 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!")
这三个代码示例都立即打印“ hello”(在看到第一个EOL时)。
此处保留旧的更复杂的代码示例,因为可能会在SO的其他帖子中进行引用和讨论
或者使用pty基于@Antti Haapala的答案:
import osimport 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!")
以上是 Python子进程readlines()挂起 的全部内容, 来源链接: utcz.com/qa/416658.html