0

当命令运行时,有什么方法可以在 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

另外,我从这个线程得到了上面的代码,但我不确定我是否理解轮询机制是如何工作的。

  1. 上面到底注册了什么?
  2. ready如果我不传递任何变量,为什么我需要timeout变量poll.poll()
4

1 回答 1

1

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

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可能需要stdin 和 stdout 流来避免死锁。但是,如果您的列表相当适中(小于 5 KB),那么您只需在开始时编写它们就可以了。poll() commands

这是一种可能的解决方案:

#! /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                
于 2013-09-16T16:25:24.997 回答