import os
import subprocess
proc = subprocess.Popen(['ls','*.bc'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out,err = proc.communicate()
print out
このスクリプトは、拡張子が.bcのすべてのファイルを出力する必要がありますが、空のリストを返します。コマンドラインでls * .bcを手動で実行すると機能します。スクリプト内で['ls'、 'test.bc']を実行しても同様に機能しますが、何らかの理由で星印が機能しません。
シェルインタープリターを介してコマンドを実行するには、Shell=True
を指定する必要があります。ただし、その場合、引数は引用符で囲まれるため、リストを最初の引数として指定できなくなります。代わりに、シェルに渡す生のコマンドラインを指定します。
proc = subprocess.Popen('ls *.bc', Shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
*
globの展開はシェルの一部ですが、デフォルトではsubprocess
はシェルを介してコマンドを送信しませんnotコマンド(最初の引数、ls
)が実行され、リテラル*
が引数として使用されます。
これは良いことです。サブプロセスドキュメントの 「よく使用される引数」セクションの警告ブロック を参照してください。主にセキュリティへの影響について説明しますが、愚かなプログラミングエラーを回避するのにも役立ちます(心配する魔法のシェルキャラクターがないため)
Shell=True
に対する私の主な不満は、通常、問題を解決するためのより良い方法があることを暗示していることです。例では、 glob
モジュール を使用する必要があります。
import glob
files = glob.glob("*.bc")
print files # ['file1.bc', 'file2.bc']
これはより速く(プロセスの起動オーバーヘッドなし)、より信頼性が高く、クロスプラットフォーム(ls
コマンドを持つプラットフォームに依存しません)