ブログ管理者のP.Hです!
下記の記事でconcurrent.futuresをモジュールを使用して、マルチスレッドで動かす方法を紹介しました。今回は、マルチプロセスで動かす方法を紹介したいと思います。
それでは、multiprocessの実装方法を紹介します。
multiprocessingモジュールでプロセス生成する
まずは、比較のために今までのやり方を紹介しようと思います。大きく2パターンあります。
- プロセスにしたい関数を引数に与えて、multiprocessingモジュールをインスタンス化 ⇒ start()
2.multiprocessingモジュールを継承したクラスのrun関数にコードを記載、クラスをインスタンス化 ⇒ start()
簡単ですが、サンプルを記載しておきます。
import multiprocessing import time from datetime import datetime class MyProcess1: # 上記の1のやり方 def __init__(self, name): self.name = name def start(self): t = multiprocessing.Process(target = self.run, args = (self.name,) ) # 引数にプロセス生成したい関数を与える t.start() # プロセス生成 def run(self, name): # self.nameを使えば、引数のnameは不要。コードの書き方のサンプルとして引数を使っています。 while True: print('[{0}] : {1}'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), name) ) time.sleep(1) class MyProcess2(multiprocessing.Process): # 上記の2のやり方 def __init__(self, name): multiprocessing.Process.__init__(self) self.name = name def run(self): # run関数にプロセス化したいコードを書く while True: print('[{0}] : {1}'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), self.name) ) time.sleep(2) if __name__ == "__main__": myprocess1 = MyProcess1("MyProcess1") myprocess1.start() myprocess2 = MyProcess2("MyProcess2") myprocess2.start() # プロセス生成
concurrent.futures のProcessPoolExecutorでプロセス生成する
それでは、新しい方法を紹介します。concurrent.futuresパッケージのProcessPoolExecutorモジュールを使って、プロセス生成する方法です。起動時に複数プロセスを一気に生成するようなとき、とてもわかりやすいです。
from concurrent.futures import ProcessPoolExecutor import time from datetime import datetime class MyProcess1: def __init__(self, name): self.name = name def run(self): while True: print('[{0}] : {1}'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), self.name) ) time.sleep(1) # 1秒ごとにprint文を表示 class MyProcess2: def __init__(self, name): self.name = name def run(self): while True: print('[{0}] : {1}'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), self.name) ) time.sleep(2) # 2秒ごとにprint文を表示 if __name__ == "__main__": process_pool = [] # プロセス生成したい関数を登録 process_pool.append(MyProcess1("MyProcess1").run) # MyProcess1のrun関数をリストに追加 process_pool.append(MyProcess2("MyProcess2").run) # MyProcess2のrun関数をリストに追加 with ProcessPoolExecutor(max_workers=2) as executor: # max_workerは同時に動かすプロセスの最大数 Noneを指定するとコア数 * 4の値になる for process in process_pool: results = executor.submit(process) # submit関数で、list内の関数をプロセス生成 for result in results: print(result)
結果は、以下のようになります。MyProcess1は1秒おきに、MyProcess2は2秒おきにメッセージが表示されます。並列処理されているのがわかると思います。
[2019-12-11 10:29:21] : MyProcess1 [2019-12-11 10:29:21] : MyProcess2 [2019-12-11 10:29:22] : MyProcess1 [2019-12-11 10:29:23] : MyProcess2 [2019-12-11 10:29:23] : MyProcess1 [2019-12-11 10:29:24] : MyProcess1 [2019-12-11 10:29:26] : MyProcess2 [2019-12-11 10:29:26] : MyProcess1 [2019-12-11 10:29:27] : MyProcess1
ProcessPoolExecutorの部分をThreadPoolExecutorに変えるとマルチプロセスになります。
ProcessPoolExecutorの場合、ps -ef
コマンドで確認すると、プロセスが3つ立ち上がります。ThreadPoolExecutorの場合は、プロセスが1つだけ立ち上がります。ProcessPoolExecutorの時に、マルチプロセスで動作しているのが確認できます。
マルチプロセスの場合は、 プロセス間でデータをやりとり方法は、下記記事を参考にしてください。