0x01 消息机制

消息机制,从字面理解,通过传递消息来触发某些事件。第一次接触到的时候,让我想到的是win的消息触发机制。在Python中,blinker主要用于解耦模块,使得代码逻辑更加清晰,其他作用我还没接触到,有待开发。
比如登陆逻辑,通常情况下像这个样子:

1
2
3
4
def login():
...
do_something()
return

如果加上验证逻辑和日志,代码可能会变得更加复杂,变成这个样子:

1
2
3
4
5
6
def login():
...
check()
log()
do_something()
return

慢慢的登陆逻辑就变得很繁琐,这时候就可以使用blinker来解耦登陆逻辑。

0x02简单的例子

在栗子中学习,首先看下基本的触发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from blinker import signal

def subscriber(sender):
print("Got a signal sent by %r" % sender)
pass

ready = signal('ready')
ready.connect(subscriber)

class Process(object):
def __init__(self, name):
self.name = name

def go(self):
ready = signal('ready')
ready.send(self)
print('processing %s'%self.name)
#complete = signal('complete')
#complete.send(self)

def __repr__(self):
return "<Process %s>"% self.name

if __name__=="__main__":
process_a = Process('a')
process_a.go()


--------------------------------------------------------------
python.exe test.py
Got a signal sent by <Process a>
processing a

Process finished with exit code 0

从blinker引入一个signal类,生成了一个“ready”的信号,并使用connect方法将这个信号实例与subscriber方法绑定。之后在Process类中,生成了一个相同名字的信号,根据blinker的机制,这两个信号是同一个实例,也就是说,signal使用的是单例模式。然后使用ready的send方法放出信号,这时候与ready信号绑定的subscriber方法触发,输出“Got a signal sent by ”,之后输出“processing a”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
from blinker import signal

def subscriber(sender):
print("Got a signal sent by %r" % sender)
pass

ready = signal('ready')
ready.connect(subscriber)

def subcomplete(sender):
print("complete a signal sent by %r"% sender)
pass
complete = signal('complete')
complete.connect(subcomplete)

class Process(object):
def __init__(self, name):
self.name = name

def go(self):
ready = signal('ready')
ready.send(self)
print('processing %s'%self.name)
complete = signal('complete')
complete.send(self)

def __repr__(self):
return "<Process %s>"% self.name

def b_subscriber(sender):
print("Caught the signal from process_b")
assert sender.name == 'b'

if __name__=="__main__":

process_b = Process('b')
ready.connect(b_subscriber,sender=process_b)
process_b.go()
process_a = Process('a')
process_a.go()
print(ready.receivers)

------------------------------------------------------------------------
Got a signal sent by <Process b>
Caught the signal from process_b
processing b
complete a signal sent by <Process b>
Got a signal sent by <Process a>
processing a
complete a signal sent by <Process a>
{6061864: <weakref at 0x00000000010F80A8; to 'function' at 0x00000000005C7F28 (subscriber)>, 11257784: <weakref at 0x000000000111FA68; to 'function' at 0x0000000000ABC7B8 (b_subscriber)>}


Process finished with exit code 0

重新绑定一个信号,将b_subscriber方法与process_b绑定,这时候ready的队列里有两个方法,并会依次触发,得到上面的输出效果。

0x03 End

作为flask中的订阅信号,其功能十分强大。