はじめに
こんにちは、Python界の情弱です。前回に引き続きpyzmqでZeroMQを触ってみます。The Guideの流れに従ってREQ/REPの次はPUB/SUBをやってみました。
参考
PUB/SUB
ZeroMQのガイドに載っているサンプルは天気予報を通知するPublisherと、それを受け取って特定の都市のデータだけフィルタして平均気温を表示するSubscriberがいるというやつだった。
コード
- weathersrv(天気予報)
import zmq import time from random import randrange context = zmq.Context() publisher = context.socket(zmq.PUB) publisher.bind("tcp://*:5556") message_id = 0 while True: zipcode = randrange(10001, 10010) temprature = randrange(0, 215) - 80 relhumidity = randrange(0, 50) + 10 update = "%05d %d %d %d" % (zipcode, temprature, relhumidity, message_id) message_id += 1 print update time.sleep(1.0) publisher.send(update)
- weathercli
import zmq import sys context = zmq.Context() subscriber = context.socket(zmq.SUB) subscriber.connect("tcp://localhost:5556") # receive only message with zipcode being 10001 zipfilter = sys.argv if len(sys.argv) > 1 else "10001 " subscriber.setsockopt(zmq.SUBSCRIBE, zipfilter) update_samples = 10 for updates in range(update_samples): message = subscriber.recv() zipcode, temprature, relhumidity, message_id = message.split() print ("zip:%s, temp:%s, relh:%s, id:%s" % (zipcode, temprature, relhumidity, message_id)) total_temp = float(temprature) print ("average temprature for zipcode '%s' was '%f'" % (zipfilter, total_temp / update_samples))
実行結果
まずSubscriberを2つ起動してからPublisherを起動する。
% python weathercli.py
% python weathercli.py
この状態でPublisher起動。
% python weathersrv.py
すると
- weathersrv.py
% python weathersrv.py 10005 -23 33 0 10001 11 56 1 10006 124 33 2 10006 7 49 3 10007 115 57 4 10009 76 10 5 10001 106 20 6 10009 -69 43 7 10007 14 24 8 10009 -24 51 9 10006 -32 58 10 10007 62 59 11 10004 2 40 12 10006 110 30 13 10006 53 31 14 ...
と表示されて、Subsriberの方は
- weathercli.py (#1)
% python weathercli.py zip:10001, temp:11, relh:56, id:1 zip:10001, temp:106, relh:20, id:6 zip:10001, temp:68, relh:57, id:21 zip:10001, temp:89, relh:34, id:34 zip:10001, temp:-73, relh:54, id:35 zip:10001, temp:45, relh:31, id:45 zip:10001, temp:-25, relh:12, id:48 zip:10001, temp:125, relh:27, id:62 zip:10001, temp:-29, relh:35, id:83 zip:10001, temp:48, relh:33, id:88 average temprature for zipcode '10001 ' was '4.800000'
- weathercli.py (#2)
% python weathercli.py zip:10001, temp:11, relh:56, id:1 zip:10001, temp:106, relh:20, id:6 zip:10001, temp:68, relh:57, id:21 zip:10001, temp:89, relh:34, id:34 zip:10001, temp:-73, relh:54, id:35 zip:10001, temp:45, relh:31, id:45 zip:10001, temp:-25, relh:12, id:48 zip:10001, temp:125, relh:27, id:62 zip:10001, temp:-29, relh:35, id:83 zip:10001, temp:48, relh:33, id:88 average temprature for zipcode '10001 ' was '4.800000'
と同じ値が表示されました。めでたし。
おまけ
最初Publisherのほうのコードをビジーループで実装してたらSubscriberが受信するメッセージが全然違ってしまってすごく焦った。