2009-09-03 14 views
2

私はPythonのサブプロセスモジュールで遊んでいましたが、いくつかの例を試しましたが、heredoc文を動作させることはできません。ここでheredocsを使用したPythonサブプロセス

は私が遊んでいた簡単な例である:私は上記のコードを実行したときに

import subprocess 
a = "A String of Text" 
p = subprocess.Popen(["cat", "<<DATA\n" + a + "\nDATA"]) 

私は次のエラーを取得する:

cat: <<DATA\nA String of Text\nDATA: No such file or directory 

私はそれが間違っているのだろうか?これも可能ですか?もしそうなら、私はそれをどうやってやりますか?


更新

ちょうどこれを行うのより良い方法があるので、これは本当のPythonプログラムで実行してはならないことを言いたかったです。

答えて

4

シェル "heredoc"サポートはシェル機能です。 subprocess.Popenはデフォルトでシェルからコマンドを実行しないため、この構文はうまく動作しません。

しかし、とにかくパイプを使用しているので、シェルのheredocサポートを使う必要はありません。ちょうど始めたプロセスのstdinパイプに文字列aを書きます。これはまさにシェルがheredocでやることです。

あなたはPopen.communicate()でこれを行うことができます。

p.communicate(a) 

communicate()関数の戻り値は、プロセスの出力が含まれています(二つの流れで、ドキュメントを参照してください)。

+0

私はShellパラメータが何をしたのか分かりませんでした。ドキュメントでは、trueに設定した場合の動作を説明しますが、falseに設定した場合はそれほど多くはありません。 – MitMaro

+1

'shell'パラメタが' False'のとき、 'subprocess'モジュールはあなたが指定したプログラム('/bin/cat')を 'Popen()'の呼び出しで指定された引数で直接実行します。 。リダイレクションやパイプなどのシェル文字の解釈が行われていない場合、プログラムは送信する内容を正確に把握します。これは 'cat'が' << DATA'で始まる名前のファイルを見つけることができなかったという理由です。 –

+0

説明をいただき、ありがとうございました。 – MitMaro

2

あなたは引数としてシェル構文をcatプログラムに渡しています。あなたはそれをそうしようとすることができます:

p = subprocess.Popen(["sh", "-c", "cat <<DATA\n" + a + "\nDATA"]) 

しかし、それ自体が間違っています。 Pythonスクリプト内でシェルスクリプトを呼び出す代わりに、Pythonの機能を使用する必要があります。

そして、あなたがすべきこの特定の場合には、そのシェルのヒアドキュメント構文は、変数を補間するので、あなたがa内のすべてのテキストをエスケープし、何DATA行がそれでありませんことを確認する必要があります。 Pythonの同等の場合


、私は(あなたが;-)だけprint(a)をしたくないと仮定して)これに最も近いアイデアを考えて生成されたプロセスの標準入力に変数の値を渡して:

p = subprocess.Popen(["program", ...], stdin=subprocess.PIPE) 
p.communicate(a) 
+0

これは役に立つ答えです。これをPythonicのやり方で行うためのコード提案があればさらに良いでしょう。 –

+0

私が質問したところでは、これはサブプロセスで遊んでいただけで、Pythonで 'cat'を呼び出すようなことは一切しません。それは本当のコードでの使用のためにもっと好奇心から外れていました。 – MitMaro

+0

"Pythonスクリプトの中でシェルスクリプトを呼び出すのではなく、Pythonの機能を使うべきです。"すべてのシェル機能がPythonで利用できるわけではありません。 heredocは、Pythonインタフェースを持たない多くの異なる種類のプログラムに供給することができ、heredocの内容はPythonで動的に生成することができます。 – user5359531

3

他の人が指摘しているように、シェルで実行する必要があります。 Popenは、これをshell = True引数で簡単にします。

>>> import subprocess 
>>> a = "A String of Text" 
>>> p = subprocess.Popen("cat <<DATA\n" + a + "\nDATA", shell=True) 
>>> A String of Text 

>>> p.wait() 
0 
関連する問題