2012-03-08 8 views
1

空のPopen()オブジェクトを作成する方法はありますか、あるいは私がしようとしていることを解決するための他の方法がありますか?Pythonで空のPopen()オブジェクトを作成しますか?

私は私が達成しようとしているかを示すためのコード例をあげる:

com = [["ls","/"],["wc"]] 
p = Popen(["echo"]) 
for c in com: 
    p = Popen(c, stdin=p.stdout,stdout=PIPE,stderr=PIPE) 
l = list(p.communicate()) 

私はシステムを含むネストされたリストを持っている私は、リストを反復処理することにより、実行したいというコマンド、これが動作するためには、もちろん、最初の反復の開始時にpが存在しなければなりません。エコーを発行することで、私がやったように私はこれを解決することができますが、もっときれいで正しい方法があるのでしょうか?

+1

*クワックquack!*この例では、 'Popen'オブジェクトである必要はありません。単にオブジェクトが適切な 'stdout'を持っています(そして、空でない" Popen "はシステム/ OSの観点からはほとんどの場合意味がありません:-) –

+0

これは、ダミーのPopenオブジェクトを作成するのに比べてstdoutのdefです。しかし、最も正しい方法は何でしょうか。 –

答えて

1

実行時に関数に渡されるパイプライン(= 1つ以上の|分離されたコマンド)を実行するだけであれば、そのすべての問題に対処する必要はありません:subprocess.Pipe(pipeline, shell=True)を使用してください。それはパイプを単独で処理します。あなたが本当に別々のパイプとしてこれらを開始したい何らかの理由で、あなたの質問に帰着する場合はこれに

(「パイプライン」は、単一の文字列、例えば"ls"または"ls/| wc"です):あなたはループを持っていますが、に初期値を必要としますそれをキックオフする。

com = [["ls","/"],["wc"]] 
p = None 
for c in com: 
    p = Popen(c, stdin=(p.stdout if p else None), stdout=PIPE, stderr=PIPE) 

(私はあなたが何をしているか誤解していたので、PS私は私の古い答えを不時着。):代わりにpopenのへの呼び出しを無駄に、私はこのようにそれを行うだろう。

+0

私はあらかじめコマンドが何であるか、またはコマンドにパイプがあるかどうかはわかりません。実際のプログラムでは、私の例のcom変数は、任意の '|'で文字列を分割することによって作成されます。それが私がループを止めた理由です。 –

+0

申し訳ありませんが、私はあなたがパイプラインを設定していることを認識していませんでした(あなたはそれを言及しませんでした)。しかし、あなたの実際のプログラムに完全なパイプラインが与えられ、それを分割するならば、この問題をすべて解決する必要はありません。分割しないでください。 'subprocess.Popen(pipeline、shell = True)'( "pipeline "あなたのプログラムが今分かち合っているものです)| – alexis

+0

ああ、申し訳ありませんが、コマンドをパイプでつなぐことについて何も言及していないことを今や理解しています。全く明らかです。 :)あなたのご意見ありがとうございました、私はいくつかのサブプロセスを読む必要があるように見えます。 –

1

UNIXでは、echoではなくtrueを使用するほうが少し好ましい場合があります。 trueは何もせず常に成功するプログラムです(チャックルのマニュアルページを参照)。

+0

ありがとう、私は真実については知らなかったが、それは私が必要なものであるようだ。 –

+0

これはどのように問題を解決するのでしょうか? 'true'は' echo'のように直ちに終了し、通信するものはありません。 – alexis

+0

ああ、私はそれを参照してください...あなたのループで 'stdin = p.stdout'を見逃してしまいました。ニースのトリック。私はあなたが各コマンドの日付を次の日付にパイプしたいと気づいていませんでした。 – alexis

1

あなたがここに欲しいことは(明らかに)パイプのシリーズです:

com[0] | com[1] | ... | com[n-1] 

最も簡単な方法は、あなたが「悪い」の文字とシェルを心配する必要はありません場合は、単にそれらすべてに参加することです一つの大きなシェルコマンドへのアップ:また

p = subprocess.Popen(' | '.join(' '.join(words) for words in com), shell=True, ...) 

、あなたが最初にSTDOUT = Noneを望んないので、あなたは、単にpは当初なしの.stdoutを持つ任意のオブジェクトであるのPSTのトリック@使用することができます。しかし、以前の各サブプロセスを閉じるシステムに依存していることにも注意してください.Popen()は出力パイプがclose()になるようにd)CPythonでは起こりますがJythonでは起こらないループ内で私が理解するように、私は実際にJythonを使用していません)。あなたは次のいずれかに各popenの()、この意志パイプの各サブコマンドからのエラー出力に標準エラー出力= subprocess.STDOUTをリダイレクトする場合

# assumes len(com) >= 1 
p0 = subprocess.Popen(com[0], stdout=subprocess.PIPE) 
# don't use stderr=subprocess.PIPE -- if you want stderr to be piped too 
# use stderr=subprocess.STDOUT, or create a stderr pipe early manually and 
# supply the fd directly; see hints in text below. 
for words in com[1:]: 
    p1 = subprocess.Popen(words, stdin=p0.stdout, stdout=subprocess.PIPE) 
    # again you don't want to set stderr to subprocess.PIPE here 
    p0.stdout.close() # now that it's going to p1, we must ditch ours 
    p0 = p1 # p1 becomes the input to any new p1 we create next time 
# at this point, use p0.communicate() to read output 

:だから、より明示的なループをお勧めします。これらのすべてをプログラムにパイプするには、最初にOSレベルのパイプオブジェクトを作成してから、それぞれをその(シングル)パイプの書き込み側に接続し、次にサブプロセスモジュールを覗き込んで、それを指す「最終」サブプロセスオブジェクトを取得する必要がありますその選択/ポーリングコードがそのパイプから任意のデータを吸い取るようにします。 (subprocess.communicate()は2本のだけなのパイプから、複数を読み込みますので、あなたは独立して、個々のサブコマンドの標準エラー出力をキャプチャすることはできません。)

注:上記のいずれもテストされていない...

関連する問題