信号

信号分为发送方和接收方。发送方发送一中信号,接收方收到信号的进程会跳入信号处理函数,执行完后再跳回原来的位置继续执行

https://www.cnblogs.com/goldsunshine/p/15426970.html

pip install blinker

使用方法

from blinker import signal

# 定义一个信号
s = signal('king')

def animal(args):
    print('hello world!')

# 信号注册一个接收者
s.connect(animal)

if "__main__" == __name__:
    # 发送信号
    s.send()

匿名信号

blinker也支持匿名信号

from blinker import Signal

#不需要指定一个具体的信号值
s = Signal()

def animal(sender):
    print('hello')

s.connect(animal)

if "__main__" == __name__:
    s.send()

组播信号

组播信号是比较能体现出信号优点的特征。多个接收者注册到信号上,发送者只需要发送一次就能传递信息到多个接收者

from blinker import signal

s = signal('king')


def animal_one(args):
    print(f'我是小钻风,今天的口号是: ')

def animal_two(args):
    print(f'我是大钻风,今天的口号是: ')


s.connect(animal_one)
s.connect(animal_two)

if "__main__" == __name__:
    s.send('大王叫我来巡山,抓个和尚做晚餐!')

订阅信号

只有当指定的消息时才发送给接收方

s = signal('king')

def animal(args):
    print(f'我是小钻风, 是我大哥')
#定义接收的信号类型,才接收
s.connect(animal, sender='大象')

if "__main__" == __name__:
    for i in ['狮子', '大象', '大鹏']:
        s.send(i)

装饰器注册信号(注册信号的另一种方法)

更简单的信号注册方法,那就是装饰器

from blinker import signal

s = signal('king')

#注册信号的另一种方法
@s.connect
def animal_one(args):
    print(f'我是小钻风,今天的口号是: ')

@s.connect
def animal_two(args):
    print(f'我是大钻风,今天的口号是: ')

if "__main__" == __name__:
    s.send('大王叫我来巡山,抓个和尚做晚餐!')

装饰器-订阅信号

s = signal('king')

@s.connect_via('大象')
def animal(args):
    print(f'我是小钻风, 是我大哥')

if "__main__" == __name__:
    for i in ['狮子', '大象', '大鹏']:
        s.send(i)

检查信号是否有接收者

s = signal('king')
q = signal('queue')

def animal(sender):
    print('我是小钻风,大王回来了,我要去巡山')

s.connect(animal)

if "__main__" == __name__:    
    res = s.receivers
    print(res)
    if res:
        s.send()
    res = q.receivers
    print(res)
    if res:
        q.send()
    else:
        print("孩儿们都出去巡山了")

检查订阅者是否订阅某一个信号

s = signal('king')
q = signal('queue')

def animal(sender):
    print('我是小钻风,大王回来了,我要去巡山')

s.connect(animal)

if "__main__" == __name__:    
    res = s.has_receivers_for(animal)
    print(res)

    res = q.has_receivers_for(animal)
    print(res)

Flask集成blinker作为解耦应用的解决方案。在Flask中,信号的使用场景如:请求到来之前,请求结束之后。同时Flask也支持自定义信号。

  • Flask Demo
from flask import Flask

app = Flask(__name__)

@app.route('/',methods=['GET','POST'],endpoint='index')
def index():
    return 'hello blinker'

if __name__ == '__main__':
    app.run()
  • flash 自定义信号
from flask import Flask
from flask.signals import _signals

app = Flask(__name__)

s = _signals.singal('msg')


def QQ(args):
    print('you have msg from QQ')

s.connect(QQ)

@app.route('/',methods=['GET','POST'],endpoint='index')
def index():
    s.send()
    return 'hello blinker'

if __name__ == '__main__':
    app.run()
  • flask自带信号
from flask import Flask
from flask.signals import _signals, request_started
import time

app = Flask(__name__)

def wechat(args):
    print('you have msg from wechat')

# 从flask中引入已经定好的信号,注册一个函数
request_started.connect(wechat)

@app.route('/',methods=['GET','POST'],endpoint='index')
def index():
    return 'hello blinker'

if __name__ == '__main__':
    app.run()

------------------------------------------------------
请求
request_started = _signals.signal('request-started')                # 请求到来前执行
request_finished = _signals.signal('request-finished')              # 请求结束后执行

模板渲染
before_render_template = _signals.signal('before-render-template')  # 模板渲染前执行
template_rendered = _signals.signal('template-rendered')            # 模板渲染后执行

请求执行
got_request_exception = _signals.signal('got-request-exception')    # 请求执行出现异常时执行
request_tearing_down = _signals.signal('request-tearing-down')      # 请求执行完毕后自动执行(无论成功与否)
appcontext_tearing_down = _signals.signal('appcontext-tearing-down') # 请求上下文执行完毕后自动执行(无论成功与否)

请求上下文中
appcontext_pushed = _signals.signal('appcontext-pushed')            # 请求上下文push时执行
appcontext_popped = _signals.signal('appcontext-popped')            # 请求上下文pop时执行

message_flashed = _signals.signal('message-flashed')                # 调用flask在其中添加数据时,自动触发