1 python-message python-message a message-oriented programming a message-oriented programming library library Lai Yonghao Lai Yonghao http://laiyonghao.com http://laiyonghao.com 2010.12.19 2010.12.19
May 19, 2015
1
python-messagepython-messagea message-oriented programming librarya message-oriented programming library
Lai YonghaoLai Yonghao
http://laiyonghao.comhttp://laiyonghao.com
2010.12.192010.12.19
2
outline
technical background
examples
features and APIs
brief introduction
implementation
3
outline
technical background
examples
features and APIs
brief introduction
implementation
4
python-message is ...
• a python publish-subscribe broker for messages within an application (NOT network).
• inspired by falcon languagesubscribe("printl", {tbp => >tbp})broadcast("printl", "Hello world!")
5
home
• http://pypi.python.org/pypi/message• http://code.google.com/p/python-message/
6
installation
• easy_install message
7
usage
import messagedef hello(context, name): print 'hello, %s.'%namemessage.sub('greet', hello)message.pub('greet', 'lai')
8
outline
technical background
examples
features and APIs
brief introduction
implementation
9
message-oriented programming
• Message-oriented programming (MOP) consists in writing program sections generating and replying to messages (happening now, in the future or even happened in the past) instead of writing direct calls.
• A message is formed by a topic and zero or more parameters.
• from Falcon wiki
10
publish-subscribe pattern
• Publish/subscribe (or pub/sub) is a messaging pattern where senders (publishers) of messages do not program the messages to be sent directly to specific receivers (subscribers).
• This decoupling of publishers and subscribers can allow for greater scalability.
• The observer pattern is a subset of the publish-subscribe pattern.
• from wikipedia
11
outline
technical background
examples
features and APIs
brief introduction
implementation
12
features
• the topic is NOT exclusively a string, all Hashable item can be used
• pub() is performed synchronously, the order by which handlers are called is the same order in which they have subscribed
• set context.discontinued = True in listerner function to interrupte publish
• listeners can unsubscribe from listening messages and declarations through the unsub() function
13
APIs
• sub/unsub• pub• declare/retract• get_declarations/has_declaration
14
sub/unsub
• sub(topic, listener, front = False)• unsub(topic, listener)
– topic:Hashable– listener:Callable, def listener(context, *a, **k):pass– front:put listener on top of the listeners list, default is F
alse
15
pub
• pub(topic, *a, **k)– topic:Hashable– a and k:parameters will be posted to the listener(s)
16
declare/retract, etc.
• declare(topic, *a, *k)– topic:Hashable– announce topic– calls all listeners– if a topic is declared, sub(topic, listener) invokes listen
er immediately
• retract(topic)– removes an existing declaration
• get_declarations()• has_declaration(topic)
17
outline
technical background
examples
features and APIs
brief introduction
implementation
18
examples
• decoupling logging from your library• dancing with process/thread/coroutine
19
decoupling logging from your library(1)
# before# foo.pylogger = logging.getLogger("prjA")def bar(): logger.debug(txt) do_sth()
20
decoupling logging from your library(2)
# afterimport messageLOG_MSG = ('log', 'foo')def bar(): messeage.pub(LOG_MSG, 'Haha, Calling
bar().') do_sth()
21
decoupling logging from your library(3)
import logginglogger = logging.getLogger("prjA")def handle_foo_log_msg(ctx, txt): logger.debug(txt)
22
decoupling logging from your library(4)
def handle_foo_log_msg(ctx, txt): import logging logging.debug(txt)
23
decoupling logging from your library(5)
import messageimport foodef handle_foo_log_msg(ctx, txt): print txtmessage.sub(foo.LOG_MSG,
handle_foo_log_msg)
24
dancing with process/thread/coroutine
• all you need is a decorate function
@new_XXXdef listener(context, *a, **k): do_sth()
25
dancing with process
from multiprocessing import Processfrom functools import wrapsdef new_process(func): @wraps(func) def _func(*a, **k): p = Process(target = func, args = a, kwargs = k) p.start() return _func
26
dancing with thread
from threading import Threadfrom functools import wrapsdef new_thread(func): @wraps(func) def _func(*a, **k): p = Thread(target = func, args = a, kwargs = k) p.start() return _func
27
dancing with coroutine(greenlet)
from greenlet import greenletfrom functools import wrapsdef new_greenlet(func): @wraps(func) def _func(*a, **k): p = greenlet(func, *a, **k) p.start() return _func
28
outline
technical background
examples
features and APIs
brief introduction
implementation
29
Talk is cheap. Show me the code.Talk is cheap. Show me the code.
Linus Torvalds
30
This is not the end, This is not the end, this is just the beginning.this is just the beginning.
31
reference
• http://en.wikipedia.org/wiki/Message_passing• http://en.wikipedia.org/wiki/Publish/subscribe• http://en.wikipedia.org/wiki/Observer_pattern• http://pubsub.sourceforge.net/• http://falconpl.org/index.ftd?
page_id=sitewiki&prj_id=_falcon_site&sid=wiki&pwid=Survival+Guide&wid=Survival%3AMessage+oriented+programming
32
Thank you !Thank you !
@laiyonghao@laiyonghao