Python BaseManager

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

月に1回は昼食で、餃子の王将で餃子2人前とライスを食べています。

というのも、アプリで2人前餃子の注文で1人前が無料というクーポンが、だいたい毎月1回配信されるからなんです。

基本的にはグループでいろいろ注文した中で餃子が1人前無料になる感じだと思いますが、まさか私のような使い方をしている人は想定外なのかもしれません。

そんなに食べられないけど、餃子は好きなので、1人前じゃ足らないし、2人前の餃子とライスでおなかいっぱいになるんです。

ちなみにクーポン利用で、餃子2人前とライスで料金はなんと429円(税込)!

さらにマイナポイントを登録しているキャッシュレスサービスで支払ったら、25%ポイント還元されるので、321円になっちゃいます。

ニンニク無し餃子も用意してくれているので、食後の匂いを気にしなくてもいいので超おすすめです。

ぜひクーポンを活用してお得に餃子を頂いちゃってください。

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

昨日の復習

昨日は、簡単にプロセス間のメモリ共有ができるManegerについて学習しました。

サーバープロセスを管理するManagerを使って、リスト型、辞書型、Namespaceに値を入れてプロセス間でデータを共有しました。

簡単にコードが書けるのですが、ValueArrayに比べて、速度が遅くなるのがデメリットでした。

Managerの詳細については、昨日の記事を参考にしてみてください。

今日は、他のマシンで走るプロセスをネットワーク越しに共有する方法を学習します。

server.py

異なるマシンでのデータやり取りなので、サーバーとクライアントを2台用意するようなイメージでserver.pyclient1.pyclient.pyの3つのファイルを作ります。

まずは、データを受け取ったり渡したりするためのserver.pyです。

import queue
from multiprocessing.managers import BaseManager

queue = queue.Queue()

class QueueManager(BaseManager):
    pass

QueueManager.register(
    'get_queue', callable=lambda: queue
)

manager = QueueManager(
    address=('127.0.0.1', 50000),
    authkey=b'masterudemy'
)
server = manager.get_server()
server.serve_forever()

最初にqueueBaseManagerをインポートします。

次にqueueオブジェクトを生成し、BaseManagerを引き継いだだけのクラスオブジェクトを作ります。

その後、9行目〜11行目でQueueManager.registerで、queueに値を出し入れできるget_queueという関数を登録します。

13行目から16行目でサーバーのIPとポート、バイトデータでauthkey(パスワードのようなもの)を指定したあと、17行目でサーバーを立ち上げて18行目のserver_forever()で処理を待つ状態にします。

client1.py

続いて、データを入力するためのclient.pyを書いていきます。

from multiprocessing.managers import BaseManager

class QueueManager(BaseManager):
    pass

QueueManager.register('get_queue')

manager = QueueManager(
    address=('127.0.0.1', 50000),
    authkey=b'masterudemy'
)
manager.connect()
queue = manager.get_queue()
queue.put('Hello')

インポートするのはBaseManagerだけで、3行目でサーバーと同じようにBaseManagerを継承したQueueManagerクラスを作っています。

6行目のQueueManager.registerで、サーバーで定義したget_queueを登録します。

8行目から11行目までは、サーバーと同じで、12行目から14行目でmanagerconnectして、queueの中にHelloを代入しています。

client2.py

続いて、client1.pyが代入したqueueを取り出すコードを書きます。

from multiprocessing.managers import BaseManager

class QueueManager(BaseManager):
    pass

QueueManager.register('get_queue')

manager = QueueManager(
    address=('127.0.0.1', 50000),
    authkey=b'masterudemy'
)
manager.connect()
queue = manager.get_queue()
print(queue.get())

13行目までは、client1.pyと同じコードになります。

14行目のget()で稼働しているサーバーにclient1.pyで保存された値を取り出しています。

実行結果

server.pyclient1.pyclient2.pyを実行してみましょう。

今回は、ターミナルからそれぞれのファイルを実行した動画を撮ってみました。

最初にsever.pyを実行してサーバーを立ち上げた状態にしておきます。

次にclient1.pyを実行して、queueHelloを代入します。

その後、client2.pyを実行すると、queueに収められているHelloを取り出すことができます。

さらに、もう一度client2.pyを実行すると、今度はqueueに何も入っていないので、最後の行のqueue.get()で値が入るのを待っている状態になり、client2.pyは終了しません。

ここでclient1.pyを実行すると、queueに再度Helloが代入され、同時にclient2.pyqueue.get()Helloが取り出されてclient2.pyが終了します。

流れをつかむ

プログラムでは、入力を待っている状態がありますが、今回のコードは、用意された箱queueに値が入っていればすぐ取り出せました。

入っていなければ、ずっと待っている状態になるわけですが、通常ならタイムアウトなどを設定してバグにつながらないようにするんだろうなと考えながらコードを読み解いていました。

ある程度のコードの流れはわかるようにはなってきたものの、これまでは単純なコードばかりなのでわかりやすいのですが、より複雑になってきたときに、しっかり一つ一つ紐解きながら、コードを読むことが必要だと感じています。

流れるようにコードを読む、あるいは書く

という領域に憧れちゃいますが、まだまだ修行が必要ですね。

それでは明日も、Good Python!