1

次の Python スクリプト:

#!/usr/bin/env python

import os
cmd = "echo Hello world | cut -d' ' -f1"
test=os.system(cmd)
print(test)

正常に実行されます(出力は ですHello)。しかし、subprocessモジュールを使用すると、次のようになります。

#!/usr/bin/env python

import subprocess
cmd = "echo Hello world | cut -d' ' -f1"
process = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
test = process.communicate()[0]
print (test)

大丈夫ではありません。出力はHello world | cut -d' ' -f1であり、期待されるのは のみHelloです。どうすれば修正できますか?

次のようなbashコマンドを使用すると、一般にサブプロセスモジュールが失敗することがわかりました。

<cmd1> | <cmd2> 
4

1 に答える 1

6

これ:

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ハンドル関数もあります。つまり、引数のリストからコマンド ラインを作成します。)quoteshell=True

ただし、通常は、 を実行すると目的のリストが得られる文字列を作成する方法を考え出すよりも、最初に引数のリストを作成する方が適切shlex.split()です。

于 2013-08-23T20:59:10.617 に答える