私は最近、サブプロセスがos.systemよりもはるかに優れていると言って、スタックオーバーフローに関するいくつかの投稿に遭遇しましたが、正確な利点を見つけるのは困難です。
私が遭遇したもののいくつかの例: https://docs.python.org/3/library/os.html#os.system
「サブプロセスモジュールは、新しいプロセスを生成し、その結果を取得するためのより強力な機能を提供します。この関数を使用するよりも、そのモジュールを使用することをお勧めします。」
それがどのようにしてより強力であるかはわかりませんが、サブプロセスを使用する方が多くの点で簡単ですが、実際には何らかの方法でより強力ですか?
別の例は次のとおりです。
https://stackoverflow.com/a/89243/3339122
subprocess対systemの利点は、より柔軟であることです(stdout、stderr、「実際の」ステータスを取得できます)コード、エラー処理の改善など)。
この投稿には2600以上の投票があります。繰り返しになりますが、より優れたエラー処理または実際のステータスコードが何を意味するのかについての詳細は見つかりませんでした。
その投稿に対するトップコメントは次のとおりです。
Os.systemを使用する理由が一目でわかりません。サブプロセスはとても良いようです。
繰り返しになりますが、いくつかの点で少し簡単になることは理解していますが、たとえばその理由はほとんど理解できません。
subprocess.call("netsh interface set interface \"Wi-Fi\" enable", Shell=True)
より良いです
os.system("netsh interface set interface \"Wi-Fi\" enabled")
誰かがそれがとても良い理由を説明できますか?
まず第一に、あなたは仲介者を切り捨てています。 subprocess.call
はデフォルトで、コマンドを検査するシェルの生成を回避し、要求されたプロセスを直接生成します。問題の効率性の側面に加えて、デフォルトのシェルの動作をあまり制御できないため、これは重要です。通常、エスケープに関しては効果がありません。
特に、通常これを行うことはありません。
subprocess.call("netsh interface set interface \"Wi-Fi\" enable")
以来
単一の文字列を渡す場合、
Shell
はTrue
でなければなりません(以下を参照)。そうでない場合、文字列は引数を指定せずに実行するプログラムを単に指定する必要があります。
代わりに、次のようにします。
subprocess.call(["netsh", "interface", "set", "interface", "Wi-Fi", "enable"])
ここで、すべての脱出する悪夢がなくなっていることに注意してください。 subprocess
はエスケープを処理するか(OSが引数を単一の文字列として要求する場合(Windowsなど))、分離された引数を関連するシステムコールに直接渡します(UNIXではexecvp
)。
これを、特にクロスプラットフォームの方法でエスケープを自分で処理する必要がある場合と比較してください(cmd
はPOSIX sh
と同じようにエスケープしません)。 (私を信じてください、cmd /k
を呼び出すときに、コマンドに対して100%安全なエスケープを提供するために、不道徳な混乱が何であるかを知りたくありません)。
また、真ん中にシェルなしでsubprocess
を使用すると、正しいリターンコードが返されます。プロセスの起動に失敗した場合、Python例外が発生します。戻りコードを取得した場合、それは実際には起動されたプログラムの戻りコードです。os.system
では、知る方法がありません。返された戻りコードが起動されたコマンド(シェルが起動に成功した場合のデフォルトの動作)からのものであるか、シェルからのエラー(起動に失敗した場合)の場合。
引数の分割/エスケープと戻りコードに加えて、起動したプロセスをより適切に制御できます。 subprocess.call
(subprocess
機能よりも最も基本的なユーティリティ関数)を使用しても、stdin
、stdout
およびstderr
をリダイレクトして、通信することができます起動されたプロセスで。 check_call
も同様であり、失敗の終了コードを無視するリスクを回避します。 check_output
は、check_call
の一般的な使用例をカバーし、+すべてのプログラム出力を文字列変数にキャプチャします。
call
と友達(os.system
と同じようにブロックされている)を通過すると、より強力な機能が使用できるようになります。特に、Popen
オブジェクトを使用すると、起動したオブジェクトを操作できます非同期に処理します。あなたはそれを開始し、おそらくリダイレクトされたストリームを介してそれと対話し、他のものを実行しながら時々実行されているかどうかを確認し、それが完了するのを待って、それに信号を送信してそれを殺します-単なるもの以外のすべてのものos.system
が提供する同期「シェルを介してデフォルトのstdin/stdout/stderrでプロセスを開始し、完了するまで待機する」。
つまり、subprocess
で要約すると、
call
&友達)でも、あなたは:Popen
:を使用する場合subprocess
はos.system
が実行できるよりも多くの方法を実行し、さらに安全で柔軟な方法(必要な場合)で-代わりにsystem
を使用する理由はありません。
多くの理由がありますが、主な理由はdocstringで直接言及されています。
>>> os.system.__doc__
'Execute the command in a subshell.'
サブプロセスが必要なほとんどすべての場合、それはサブシェルを生成することは望ましくないです。これは不要で無駄であり、複雑さがさらに増し、いくつかの新しい脆弱性と障害モードが発生します。 subprocess
モジュールを使用すると、仲介者が排除されます。