2011-07-03 16 views
1

私は多くのシェル関数を呼び出すpythonスクリプトを持っています。スクリプトは端末から対話的に実行できます。その場合はすぐに出力を表示するか、crontabによって呼び出されます。この場合、エラー出力を電子メールで送信します。サブプロセスを使ってシェル出力をリダイレクト

私はシェル関数を呼び出すためのヘルパー関数を書きました:

import subprocess 
import shlex 
import sys 

def shell(cmdline, interactive=True): 
    args = shlex.split(cmdline.encode("ascii")) 
    proc = subprocess.Popen(args, stdout=subprocess.PIPE, 
     stderr=subprocess.PIPE) 
    val = proc.communicate() 
    if interactive is True: 
     if proc.returncode: 
      print "returncode " + str(proc.returncode) 
      print val[1] 
      sys.exit(1) 
     else: 
      print val[0] 
    else: 
     if proc.returncode: 
      print "" 
      # send email with val[0] + val[1] 

if __name__ == "__main__": 
    # example of command that produces non-zero returncode 
    shell("ls -z") 

を私がいる問題は二つあります。コマンドが完全以来、通信完了するまでシェルコマンドが終了する間(例えば数分)かかり

1)インタラクティブモードでは、私は出力をバッファリング)(何も表示されません。それが来ると出力を表示し、バッファリングを避ける方法はありますか?リターンコードをチェックする方法も必要です。それで、私はcommunications()を使用しています。

2)私が呼び出すシェルコマンドの中には、多くの出力(例:2MB)を生成するものがあります。 communications()のdocumentationには、「データサイズが大きい場合や無制限の場合は、このメソッドを使用しないでください。誰が "large"の大きさを知っていますか?

答えて

2

1)と通信する場合、と通信すると、サブプロセスの出力がキャプチャされるため、標準出力に何も送信されません。サブプロセスが終了したときに出力が表示される唯一の理由は、自分で印刷するためです。

あなたがそれを見てどちらかたいので、それはそれをキャプチャしたり、すべてをキャプチャし、唯一の終わりにそれで何かを実行していないとして、あなたはSTDOUTstderrのを残すことによって、それは対話モードでの動作方法を変更することができます〜なし。これにより、サブプロセスはプログラムと同じストリームを使用します。あなたへの呼び出しを置き換えることもあるでしょうがを待つを呼び出してを伝える:

if interactive is True: 
    proc = subprocess.Popen(args) 
    proc.wait() 
    if proc.returncode: 
     print "returncode " + str(proc.returncode) 
     sys.exit(1) 
else: 
    proc = subprocess.Popen(args, stdout=subprocess.PIPE, 
     stderr=subprocess.PIPE) 
    val = proc.communicate() 
    if proc.returncode: 
     print "" 
     # send email with val[0] + val[1] 

2)大きすぎると、それはすべての多くに依存しますので、「メモリに保存するには大きすぎる」です要因。あなたの状況でメモリに2MBのデータを一時的に保存しても問題ない場合、心配することはありません。

関連する問題