显示具有共享环境的shell命令的输出

时间:2013-09-16 15:30:56

标签: python shell python-2.x

有没有办法在Python中显示shell命令的输出,因为命令运行?

我有以下代码将命令发送到特定 shell(在本例中为/bin/tcsh):

import subprocess
import select

cmd = subprocess.Popen(['/bin/tcsh'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

poll = select.poll()
poll.register(cmd.stdout.fileno(),select.POLLIN)

# The list "commands" holds a list of shell commands
for command in commands:
  cmd.stdin.write(command)

  # Must include this to ensure data is passed to child process
  cmd.stdin.flush() 

  ready = poll.poll()
  if ready:
     result = cmd.stdout.readline()
     print result

另外,我从this thread获得了上面的代码,但我不确定我是否了解轮询机制的工作原理。

  1. 上面注册了什么?
  2. 如果我没有将ready传递给timeout,为什么我需要变量poll.poll()

1 个答案:

答案 0 :(得分:1)

是的,当命令运行时,完全可以显示shell comamand的输出。有两个要求:

1)该命令必须刷新其输出。

许多程序根据输出是连接到终端,管道还是文件来缓冲输出。如果它们连接到管道,它们可能会更频繁地将它们的输出写入更大的块。对于您执行的每个程序,请参阅其文档。例如,/bin/cat'的某些版本具有-u开关。

2)你必须逐个阅读它,而不是一次性阅读。

您的程序必须从输出流中一次构建一个部分。这意味着你不应该这样做,每次都读取整个流:

cmd.stdout.read()
for i in cmd.stdout:
list(cmd.stdout.readline())

但相反,你可以做其中一个:

while not_dead_yet:
    line = cmd.stdout.readline()

for line in iter(cmd.stdout.readline, b''):
    pass

现在,针对您的三个具体问题:

  
    

有没有办法在Python中显示shell命令的输出,因为命令运行?

  

是的,但前提是您运行的命令在运行时输出,并且不会将其保存到最后。

  
    

上面究竟注册了什么?

  

文件描述符,当读取时,使子进程的输出可用。

  
    

如果我没有向poll.poll()传递任何超时,为什么我需要变量就绪?

  

你没有。您也不需要poll()。如果您的commands列表相当大,则可能需要poll() 两者 stdin和stdout流以避免死锁。但是如果你的commands列表相当适中(小于5K字节),那么你可以在开头编写它们。

以下是一种可能的解决方案:

#! /usr/bin/python

import subprocess
import select

# Critical: all of this must fit inside ONE pipe() buffer
commands = ['echo Start\n', 'date\n', 'sleep 10\n', 'date\n', 'exit\n']

cmd = subprocess.Popen(['/bin/tcsh'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

# The list "commands" holds a list of shell commands
for command in commands:
  cmd.stdin.write(command)

  # Must include this to ensure data is passed to child process
  cmd.stdin.flush()

for line in iter(cmd.stdout.readline, b''):
    print line