0

コマンドの実行時にシェルコマンドの出力をPythonで表示する方法はありますか?

特定のシェル (この場合は/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

はい、コマンドの実行時にシェルコマンドの出力を表示することは完全に可能です。次の 2 つの要件があります。

1) コマンドはその出力をフラッシュする必要があります。

多くのプログラムは、出力が端末、パイプ、またはファイルに接続されているかどうかに応じて、出力を異なる方法でバッファリングします。それらがパイプに接続されている場合、出力をはるかに大きなチャンクに書き込む頻度がはるかに低くなる可能性があります。実行するプログラムごとに、そのドキュメントを参照してください。/bin/cat'たとえば、の一部のバージョンには-uスイッチがあります。

2) 一気に読むのではなく、少しずつ読む必要があります。

プログラムは、出力ストリームから一度に 1 つずつ構成する必要があります。これは、ストリーム全体を一度に読み取る次のようなことを行うべきではないことを意味します。

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

さて、あなたの3つの具体的な質問について:

コマンドの実行時にシェルコマンドの出力をPythonで表示する方法はありますか?

はい。ただし、実行中のコマンドが実行時に出力を出力し、最後に保存しない場合に限ります。

上記に登録されているものは正確には何ですか?

読み取り時にサブプロセスの出力を利用可能にするファイル記述子。

poll.poll() にタイムアウトを渡さないのに、変数の準備が必要なのはなぜですか?

あなたはそうしない。も必要ありませんpoll()commandsリストがかなり大きい場合、デッドロックを回避するために stdin ストリームと stdout ストリームのpoll() 両方が必要になる可能性があります。しかし、commandsリストがかなり控えめ (5K バイト未満) であれば、最初にそれらを書くだけで問題ありません。

考えられる解決策の 1 つを次に示します。

#! /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 に答える