Python プロセス間通信の基本

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

暑い暑いと言っていたのに、ここ数日で一気に朝晩が冷え込むようになりました。

ほんと最近の天候ってどうなってるんでしょうか?

涼しいのを通り越して寒いと感じるんですから、ほんとびっくりです。

個人的には、暑いより寒いほうがいいのですが、寒いより涼しいのほうがうれしいのは私だけではないですよね。

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

昨日の復習

昨日は、map_asyncimapを使っての非同期処理を学習しました。

Poolを使ったmapでは、並列処理はできましたが、非同期処理にはなっていませんでした。

同じ処理を非同期で行うことができるのがmap_asyncimapでした。

imapを使うとイテラブルオブジェクトが生成されるので、その中からデータを取り出して出力するために、リスト内包表記のforループを使いました。

くわしくは、昨日の記事をごらんください。

今日は、プロセス間通信について学習します。

スレッドとの違い

マルチスレッドの場合は、メモリを共有していたので、スレッド間のデータのやり取りが簡単でした。

プロセスの場合は、それぞれのプロセスが使うメモリが別々なので、ひと工夫必要になってきます。

スレッド間通信については、こちらの記事でおさらいしておきましょう。

スレッドの復習

まずは、スレッドのメモリ共有について、少し戻ってマルチスレッドのコードを復習してみます。

import logging
import threading

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

def worker1(d, lock):
    with lock:
        i = d['x']
        d['x'] = i + 1
    logging.debug(d)

def worker2(d, lock):
    with lock:
        i = d['x']
        d['x'] = i + 1
    logging.debug(d)

if __name__ == '__main__':
    d = {'x': 0}
    lock = threading.Lock()
    t1 = threading.Thread(target=worker1, args=(d, lock))
    t2 = threading.Thread(target=worker2, args=(d, lock))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    logging.debug(d)

ThreadLockを使ってスレッド間で辞書型データのdを共有して操作しています。

実行結果

Thread-1: {'x': 1}
Thread-2: {'x': 2}
MainThread: {'x': 2}

dは、メインスレッドと2つのスレッド間で共有されているので、最初value0でしたが、16行目と27行目の出力では、9行目と15行目で1ずつプラスされて2に増えています。

プロセス間通信

続いてプロセスで同じことを実行してみます。

import logging
import multiprocessing

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

def worker1(d, lock):
    with lock:
        i = d['x']
        d['x'] = i + 1
    logging.debug(d)

def worker2(d, lock):
    with lock:
        i = d['x']
        d['x'] = i + 1
    logging.debug(d)

if __name__ == '__main__':
    d = {'x': 0}
    lock = multiprocessing.Lock()
    t1 = multiprocessing.Process(target=worker1, args=(d, lock))
    t2 = multiprocessing.Process(target=worker2, args=(d, lock))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    logging.debug(d)

実行結果

Process-1: {'x': 1}
Process-2: {'x': 1}
MainProcess: {'x': 0}

Lockはプロセスでも使えるので、threading.Threadmultiprocessing.Processに変更しています。

もちろん、最初のインポートをmultiprocessingに変えて、ロギングのthreadNameprocessNameに変更しています。

実行結果は、メインプロセスのdは、最初に定義した値のままで、他の2つのプロセスは1になっています。

スレッドと違い、プロセスの場合は、それぞれのプロセスで別々のメモリを使っているので、それぞれのプロセスで別々の変数dが作成されます。

同じ変数名でも別々のものということですね。

違いを踏まえて

スレッドとプロセスの違いを理解できたでしょうか?

プロセスにもスレッドと同じように、データを共有する方法もあるわけですが、まずは、プロセスとスレッドの違いを理解した上で、明日からプロセス間通信のコードを学んでいきましょう。

それでは明日もGood Python!