これ:
echo Hello world | cut -d' ' -f1
… は実際にはコマンドではなく、シェル スクリプトの一部です。したがって、シェルに実行させる必要があります。
コンストラクターに追加shell=True
するだけでこれを行うことができます。Popen
ドキュメントは、これがどのように機能するかを説明しています。また、シェルなしで同じことを行うためのより良い方法についても説明しています。例えば:
p1 = Popen(['echo', 'Hello', 'world'], stdout=PIPE)
p2 = Popen(['cut', "-d' '", '-f1'], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()
test = p2.communicate()[0]
一方、split
コマンドラインで使用することはほとんどありません。実際、あなたの例は、使用したくない理由を正確に示しています。
>>> cmd = "echo Hello world | cut -d' ' -f1"
>>> cmd.split()
['echo', 'Hello', 'world', '|', 'cut', "-d'", "'", '-f1']
-d' '
2 つの引数 と に分割され-d'
ていることに注意してください'
。
を使用している場合はshell=True
、引数を分割しようとしないでください。として文字列を渡すだけcmd
です:
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
シェルを使用していない場合、これを行う正しい方法はshlex
モジュールを使用することです。
>>> shlex.split(cmd)
['echo', 'Hello', 'world', '|', 'cut', '-d ', '-f1']
今回は"-d' '"
になっていることに注意してください。"-d "
一見すると奇妙に思えるかもしれませんが、実際にはシェルが行うこと、およびユーザーが望むこととまったく同じです。cut
プログラムはオプションとしてスペースを取得しますd
。(つまり、引用符はシェルに対するものであり、シェルが実行するプログラムに対するものではありません。)
(モジュールには、まったく逆の目的で使用できるshlex
ハンドル関数もあります。つまり、引数のリストからコマンド ラインを作成します。)quote
shell=True
ただし、通常は、 を実行すると目的のリストが得られる文字列を作成する方法を考え出すよりも、最初に引数のリストを作成する方が適切shlex.split()
です。