Python Popen _with_实时输入/输出控制

时间:2017-03-01 19:03:10

标签: python

我已经搜索并试验了一个多小时,并且似乎没有办法同时执行'here document'并逐行获取输出:

python = '''var="some character text"
print(var)
print(var)
exit()
 '''

from subprocess import Popen, PIPE, STDOUT
import shlex

def run_process(command):
  p = Popen(shlex.split(command), stdin=PIPE, stdout=PIPE, stderr=STDOUT)
  p.stdin.write(python)
  while True:
    output = p.stdout.readline()
    if output == '' and p.poll() is not None:
      break
    if output:
      print output.strip()
  rc=p.poll()
  return rc

run_process("/usr/bin/python")

以上代码无限期挂起。是的,它是一条蛇吃它的尾巴,但它只是为了证明这个概念。

问题是我的子进程需要很长时间才能运行,我需要能够在没有等待数小时的情况下查看输出是否有任何问题。任何提示?感谢。

1 个答案:

答案 0 :(得分:0)

在交互式模式和非交互式模式下运行时,Python解释器的行为会有所不同。从python(1)手册页:

  

在非交互模式下,整个输入在执行之前进行解析。

当然,“整个输入”由EOF分隔,并且您的程序从不发送EOF,这就是它挂起的原因。

Python如果是stdin is a tty,则以交互模式运行。您可以使用Ptyprocess库生成一个tty为stdin的进程。或者使用Pexpect库(基于Ptyprocess),甚至包括ready-made REPL wrappers用于Python和其他程序。

但是如果用sed替换Python - 当然没有交互模式 - 该程序仍然不起作用:

sed = '''this is a foo!\n
another foo!\n
 '''

from subprocess import Popen, PIPE, STDOUT
import shlex

def run_process(command):
  p = Popen(shlex.split(command), stdin=PIPE, stdout=PIPE, stderr=STDOUT)
  p.stdin.write(sed)
  while True:
    output = p.stdout.readline()
    if output == '' and p.poll() is not None:
      break
    if output:
      print output.strip()
  rc=p.poll()
  return rc

run_process("/bin/sed -e 's/foo/bar/g'")

这是由不同的问题引起的:sed中的输出缓冲。某些程序可以选择禁用缓冲。特别是,sed和Python都有一个-u选项,可以解决这个问题:

run_process("/bin/sed -ue 's/foo/bar/g'")