2016-05-31 24 views
1

GUIベースのソフトウェアから複数のbashルーチン を起動しようとしています。私が直面している問題は配管の問題です。ここで テストのbashスクリプト(bashScriptTest.sh):壊れたパイプのエラーPythonのサブプロセス

#!/bin/bash 
#---------- Working 
ls | sort | grep d > testFile.txt 
cat testFile.txt 
#---------- NOT working 
echo $RANDOM > testFile2.txt 
for i in `seq 1 15000`; do 
    echo $RANDOM >> testFile2.txt 
done 
awk '{print $1}' testFile2.txt | sort -g | head -1 

そして、ここでエラーを作成するPythonスクリプト:

import subprocess 
# 
with open('log.txt','w') as outfile: 
    CLEAN=subprocess.Popen("./bashScriptTest.sh", stdout=outfile, stderr=outfile) 
    print CLEAN.pid 
    OUTSEE=subprocess.Popen(['x-terminal-emulator', '-e','tail -f '+outfile.name]) 

あなたはPythonスクリプトを実行しているからわかるように、壊れたパイプのエラーは、最初の3つのパイプ(最初の行)ではなく、代わりにawkによって行われた巨大な作業の後に が発生しました。 私は膨大な量のルーチンとサブルーチンをbash で管理する必要があり、またシェルを使用する必要があります。== Trueフラグは何も変更しません。 私はすべてのpythonの方法ですべてを書き込もうとしましたが、残念ながら 機会がありません。私はPython内のすべてのパイピングステップを書き直すことができます。 もう1つのことは、ターミナル内でbashスクリプトをテストすると、すべてが正常に動作することです。 本当にありがとうございます。前もって感謝します!

EDIT 1:

エラーを含むログ・ファイルは言う:

bashScriptTest.sh 
log.txt 
stack.txt 
testFile2.txt 
test.py 
3 
sort: write failed: standard output: Broken pipe 
sort: write error 
+0

エラーメッセージとスタックトレースを追加してください! :) –

+0

いつプロセスが終了するのを待っていますか? –

+0

@AndréLaszlo私は質問を編集しました! – Mat

答えて

1

わかりましたので、これは少し曖昧ですが、ちょうどので、私は一方で同様の問題に出会っていることが起こりますしばらく前にquestion on the python-tutor mailing listを調査しています。

サブプロセスモジュール(Python)とbashを直接実行しているときの動作が異なる理由は、すべての子プロセス(グローバル)に対してSIGPIPEの処理をSIG_IGN(無視)に優先します。それにより-1フラグに、sortコマンドから標準出力の最初の行を印刷した後

awk '{print $1}' testFile2.txt | sort -g | head -1 

次のパイプラインが実行さ

... headは終了します。 sortコマンドがstdoutにさらに多くの行を書き込もうとすると、SIGPIPEが発生します。

SIGPIPEのデフォルト動作。パイプラインがbashのようなシェルで実行されると、 sortコマンドを終了することです。

前述したように、Pythonはデフォルト動作をSIG_IGN(無視)で上書きします。そのため、この奇妙で、やや説明できない動作に終わります。


これですべてがうまくいきましたが、今何をすべきか疑問に思うかもしれません。これは、使用しているPythonのバージョンに依存します。

Python 3.2以降では、すでに設定されています。 subprocess.Popen in 3.2にはrestore_signalsというパラメータが追加されており、デフォルトではTrueに設定されており、これ以上の操作を行わなくても問題は効果的に解決されます。

以前のバージョンでは、引数には、subprocess.Popenのように、callableを指定することができます。

import signal 
def default_sigpipe(): 
    signal.signal(signal.SIGPIPE, signal.SIG_DFL) 

# ... 

with open('log.txt','w') as outfile: 
    CLEAN=subprocess.Popen("./bashScriptTest.sh", 
          stdout=outfile, stderr=outfile 
          preexec_fn=default_sigpipe) 

私は助けてくれることを願っています!

EDIT:あなたのプログラムは実際にAFAICTが正しく機能していることに注意してください。シェルで直接スクリプトを実行するときに通常は表示されないエラーメッセージが表示されているだけです(前述の理由による)。

参照:

+0

本当にありがとうございました...私の問題は、Pythonにとっては本当に奇妙な問題を修正しました。 開発中に彼らが解決したことをうれしく思います。 – Mat

+0

'default_sigpipe()'関数は状態をグローバルに変更します。私はこれが間違いだと思う。これを一度行うだけで、同じ効果が得られます: 'signal.signal(signal.SIGPIPE、signal.SIG_DFL)' – aramaki

関連する問題