はじめに
開発部の ikasat です。
皆さんは git
, ssh
, rsync
のような外部コマンドを呼び出すスクリプトを書きたくなったことはありますか?
個人的にこの類のスクリプトは最初はシェルスクリプトとして書くのですが、改修を重ねるうちに肥大化して処理も複雑になり、
後から Python のような汎用プログラミング言語で書き直すことがよくあります。
外部コマンド呼び出しを書き直す際に、Git 操作のために pygit2、
SSH 接続のために paramiko のようなライブラリをわざわざ使うのは大がかりだったり、
rsync
に相当するようなこなれたライブラリが存在しなかったりする場合があります。
そのような時は標準ライブラリの subprocess
モジュールを利用し、Python から外部コマンドを呼び出すことになるでしょう。
しかしながら、Python のチュートリアルページには subprocess
モジュールの解説はなく、
いきなり標準ライブラリのリファレンスを読むことになります。
subprocess
モジュールはバージョンアップに従いAPIが多数追加されており、また各種OSの事情が同じ箇所に記載されているため、一見して利用法をなかなか掴みにくいです。
この記事では対象環境を Linux に絞り、シェルスクリプトと Python スクリプトを対比した上で subprocess
モジュールの典型的な利用方法について述べます。
また、記事の後半では subprocess
モジュールの詳細に立ち入り、込み入ったケースでの注意点について記載します。
対象読者
subprocess
を雰囲気で利用している人
- 具体的には公式のリファレンスや巷の解説記事を多少読んで
import subprocess
したことがある人
- はじめに
- 対象読者
- 対象環境
- シェルスクリプトとPythonの比較
- コマンドを起動する(最も単純な使い方)
- 終了ステータスを取得する
- 標準出力を捕捉する
- 標準入出力をリダイレクトする
- 標準エラー出力を標準出力にマージして捕捉する
- 出力を全て捨てる
- 終了ステータスが0でなければ例外を発生させる
- Pythonのバイト列・文字列をコマンドに渡す
- 並行処理を行う
- Popen と communicate で標準入出力を扱う
- パイプ処理を行う
- タイムアウトを設定する
- シェル経由でコマンドを起動する(要注意)
- subprocessの詳細仕様と内部実装
- プロセス間通信の流れ(概要)
- プロセス間通信の実装(詳細)
- 子プロセス同士をパイプする際に close が必要な理由
- Pythonとパイプ書き込みエラー
- デッドロックと communicate
- おわりに
- 採用情報
続きを読む