Python 親子間でデータのやり取りをするプロセス Pipe

Python学習【365日チャレンジ!】225日目のマスターU(@Udemy11)です。

最近釣りにいってもタチウオが1匹とかアジが数匹とかしか釣れなかったので、冷凍してまとめて料理しようと思っていました。

とりあえず夕食分くらいには溜まったので、アジとタチウオ、セイゴ(スズキのちいさいの)を素揚げして、南蛮漬けを作りました。

アジの南蛮漬け

アジは中途半端な大きさだったので、骨がきついかなと思ったのですが、酢を多めに入れて一晩おいたら、骨はそんなに気にならなず美味しく食べることができました。

南蛮漬けは、素揚げよりちょっとだけ手間をかけた料理なので、自分で作るとほんとおいしいんですよね。

もちろん、クックパッドなしでは作れませんけど。。。

それでは、今日もPython学習をはじめましょう。

昨日の復習

昨日は、プロセス同士のデータのやり取りをするプロセス間通信の基本を学習しました。

スレッドの場合はスレッドが使うメモリは共有されて、保存したデータもスレッド間で同じものを利用していました。

プロセスの場合は、それぞれのプロセスがそれぞれのメモリを使うので、同じ変数名でもコピーされて別々のデータとして取り扱われていました。

スレッドとプロセスの基本的な違いについては、昨日の記事をごらんください。

今日は、親子でデータのやり取りができるパイプ(Pipe)について学習します。

Pipe

昨日学習したように、マルチプロセスは別々のメモリを使うので、基本はデータを共有しませんが、入力、出力が対になったプロセスでデータの入出力ができるものにPipeがあります。

コマンドラインで使う|(パイプ)は、コマンドの入出力を別のコマンドに引き渡す処理をしますが、マルチプロセスでは、親子間の橋渡しの役割を持っています。

import logging
import multiprocessing
import time

logging.basicConfig(
    level=logging.DEBUG, format='%(processName)s: %(message)s'
)

def func(conn):
    conn.send(['test', 1, 2])
    time.sleep(2)
    conn.close

if __name__ == '__main__':
    parent_conn, child_conn = multiprocessing.Pipe()
    p = multiprocessing.Process(target=func, args=(parent_conn, ))
    p.start()
    logging.debug(child_conn.recv())

7行目まではこれまでと同じコードです。

15行目でPipeparent_connchild_connを定義して、16行目でターゲットに関数func、引数にparent_connを代入したプロセスを作成して次の行でプロセスをスタートさせています。

9行目から12行目で実行する関数を定義していますが、send()メソッドを使いparent_connから引数のリストを送って、18行目のロギングの中でrecv()メソッドを使ってchild_connでリストを受け取っています。

12行目では、conn.closePipeを閉じています。

11行目のtime.sleep(2)は特に必要ありませんが、リスト['test', 1, 2]を送ってから2秒後にプログラムが終了するように記述しています。

parent_connがデータを受け取ると、すぐにchild_connにデータが渡されるので、18行目でリストが表示されてから2秒後にプログラムが終了します。

実行結果

MainProcess: ['test', 1, 2] #この行が出力されたあと2秒後に終了する

時系列で考える

Pythonは基本的に上から順番にコードが実行されていきますが、処理があっち行ったりこっち行ったりするので、今どこの処理をしているのか理解してコードを書くことは重要です。

p.start()によってプロセスが立ち上がるわけですが、関数funcに値が入ったらすぐにchild_connで受け取った値を表示しているので、time.sleep(2)が実行されるのはその後だとか、p.start()のあとにp.join()を入れると関数funcが終了するのを待って次の行の処理をするので、受け取った値を表示するのはコードを実行してから2秒後で、同時にプログラムを終了するとか、いろいろ試して時系列でどうなっているのか考えてみましょう。

まー、時系列という言葉自体、もっと長いスパンのことだと思いますが、処理される順序を考えながら、コードを読み解く癖をつけましょう。

それでは、明日もGood Python!