みなさんこんにちは。どんぶラッコです。
とある事情で、自分が作った webサービスを ローカルで立ち上げて、seleniumでスクレイピングするというシステムを構築しました。
なのでやることはこんな感じ。
- ローカルサーバを立ち上げる
- スクレイピングスクリプトを実行する
- ローカルサーバを落とす
単純といえば単純なのですが、ローカルサーバのON / OFF も手動ではなくプログラム側から実行したい…
そんな時に使える subprocess
というモジュールがあるので、そのご紹介をします!
subprocessとは?
subprocess モジュールは新しいプロセスの開始、入力/出力/エラーパイプの接続、リターンコードの取得を可能とします。このモジュールは以下の古いモジュールや関数を置き換えることを目的としています:
https://docs.python.org/ja/3/library/subprocess.html
あまりイメージがつかない方は、プログラムの関数のようなものだと思っておけばOKです。あるプロセスの中でプロセスの塊を実行してくれるモジュールですね。
基本的には run
メソッドを使うことが推奨されています。
subprocess.run(['処理コマンド'])
今回はこの run()
メソッドに加え、Popen()
を使用します。
proc = subprocess.Popen(['処理コマンド'])
proc.terminate() # サブプロセスを終了
Popen()
メソッドは新しいプロセスとしてプログラムを実行してくれます。なので、並列処理や非同期処理と呼ばれる使い方ができるんですね。
今回は、ローカルサーバを立ち上げるので、プロセスが1本だと占有されたままになってしまい、それ以降の処理が走りません。なので、Popen()
メソッドを使って別プロセスとして処理してもらうことにします。
サンプルコード
では、実際に作ったコードです。上記のことが頭に入っていればすぐに理解できますよ!
import subprocess
# webサーバ用のファイルがある場所
WEB_PATH = '/hogehoge/hogehoge/'
# ローカルサーバが立ち上がってる間に実行させたい pythonファイル名
PYTHON_PATH = 'hello.py'
# サブプロセスを起動
proc = subprocess.Popen(['php', '-S', '127.0.0.1:3000', '-t', WEB_PATH])
try:
# ここに処理を記述 or ファイル呼び出し
subprocess.run(['python', PYTHON_PATH])
except:
print('error')
# サブプロセスを終了
proc.terminate()
9行目で proc = subprocess.Popen()
を呼び出しています。新規プロセスを立ち上げて、そちらでローカルサーバを立ち上げています。
変数に代入することで作成したサブプロセスを触ることができます。最後の行で proc.terminate()
を実行して終了しています。
また、その間に subprocess.run(['python', PYTHON_PATH])
を実行し、自分が作成したpythonファイルを実行しています。
これで最初に僕が望んだ挙動になりました!
みなさんもチャレンジしてみてください♪