简介
Django、Flask、scrapy都包含了一个“信号分配器”,使得当一些动作在框架的其他地方发生的时候,解耦的应用可以得到提醒。
通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者,这是特别有用的设计因为有些代码对某些事件是特别感兴趣的,比如删除动作。
下面,分别介绍一下三种信号的使用示例。
Django信号
很多数情况下,我们需要在操作数据库之前或者之后做某些操作,比如说写个日志之类的,我们当然可以找到每一个sql语句,在其前后加一段代码,
但是,这不但浪费时间,还为以后的维护增加了难度,这个时候,就体现出信号的作用了。下面的代码是Django中对数据库增加一条数据的操作:
?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 |
# models.py
from django.db import models
class User(models.Model):
title = models.CharField(max_length = 32 )
# views.py
from django.shortcuts import render,HttpResponse
from app01 import models
def func1(request):
models.User.objects.create(title = '付勇' )
return HttpResponse( '创建成功' )
def func2(request):
models.User.objects.create(title = '小男孩' )
return HttpResponse( '创建成功' )
def func3(request):
models.User.objects.create(title = '小少年' )
return HttpResponse( '创建成功' )
def func4(request):
models.User.objects.create(title = '小青年' )
return HttpResponse( '创建成功' )
|
这个时候,如果我们想要在每增加一条数据之后在控制台打印一句话(当然可以换成其他操作)的话,就可以在项目下的__init__.py中进行信号操作,代码如下:
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
from django.db.models import signals
def before_save1( * args, * * kwargs):
print ( 'before_save1--->' ,args,kwargs)
def before_save2( * args, * * kwargs):
print ( 'before_save2--->' ,args,kwargs)
def after_save1( * args, * * kwargs):
print ( 'after_save2---->' ,args,kwargs)
# 在增加数据之前执行before_save1函数
signals.pre_save.connect(before_save1)
# 在增加数据之前执行before_save2函数
signals.pre_save.connect(before_save2)
# 在增加数据之后执行after_save1函数
signals.post_save.connect(after_save1)
|
Django中的内置信号:
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Model signals
pre_init # django的modal执行其构造方法前,自动触发
post_init # django的modal执行其构造方法后,自动触发
pre_save # django的modal对象保存前,自动触发
post_save # django的modal对象保存后,自动触发
pre_delete # django的modal对象删除前,自动触发
post_delete # django的modal对象删除后,自动触发
m2m_changed # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
class_prepared # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
Management signals
pre_migrate # 执行migrate命令前,自动触发
post_migrate # 执行migrate命令后,自动触发
Request / response signals
request_started # 请求到来前,自动触发
request_finished # 请求结束后,自动触发
got_request_exception # 请求异常后,自动触发
Test signals
setting_changed # 使用test测试修改配置文件时,自动触发
template_rendered # 使用test测试渲染模板时,自动触发
Database Wrappers
connection_created # 创建数据库连接时,自动触发
|
Flask信号
项目功能复杂,代码量越大,就越需要做业务解耦。否则在其之上做开发和维护是很痛苦的,尤其是对于团队的新人。
Flask从0.6开始,通过Blinker提供了信号支持。信号就是在框架核心功能或者一些Flask扩展发生工作时所发送的通知,用于帮助你解耦应用。
如果需要在Flask中使用信号,需要先安装blinker组件:
?1 |
pip install blinker
|
使用信号代码如下:
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
from flask import Flask,render_template
from flask import signals
app = Flask(__name__)
def x1(arg):
print ( 'x1' )
def x2(arg):
print ( 'x2' )
# 在发起请求之前执行x1函数
signals.request_started.connect(x1)
# 在发起请求之前执行x2函数
signals.request_started.connect(x2)
@app .route( '/index' )
def func():
print ( '视图函数' )
return "ok"
if __name__ = = '__main__' :
app.run()
|
Flask中内置的信号:
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
1. template_rendered:模版渲染完成后的信号。
2. before_render_template:模版渲染之前的信号。
3. request_started:模版开始渲染。
4. request_finished:模版渲染完成。
5. request_tearing_down:request对象被销毁的信号。
6. got_request_exception:视图函数发生异常的信号。一般可以监听这个信号,来记录网站异常信息。
7. appcontext_tearing_down:app上下文被销毁的信号。
8. appcontext_pushed:app上下文被推入到栈上的信号。
9. appcontext_popped:app上下文被推出栈中的信号
10. message_flashed:调用了Flask的`flashed`方法的信号。
|
Scrapy信号
Scrapy使用信号来通知事情发生。您可以在您的Scrapy项目中捕捉一些信号(使用 extension)来完成额外的工作或添加额外的功能,扩展Scrapy。
虽然信号提供了一些参数,不过处理函数不用接收所有的参数 - 信号分发机制(singal dispatching mechanism)仅仅提供处理器(handler)接受的参数。
使用的时候新建一个py文件,如ext.py,代码如下:
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
from scrapy import signals
class MyExtend( object ):
def __init__( self ):
pass
@classmethod
def from_crawler( cls , crawler):
self = cls ()
# 爬虫启动的时候执行x1方法
crawler.signals.connect( self .x1, signal = signals.spider_opened)
# 爬虫启动的时候执行x2方法
crawler.signals.connect( self .x2, signal = signals.spider_closed)
return self
def x1( self , spider):
print ( 'open' )
def x2( self , spider):
print ( 'close' )
|
Scrapy内置的信号:
+ View Code?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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
engine_started
scrapy.signals.engine_started()
当scrapy引擎启动爬取时发送该信号
该信号支持返回deferreds
当信号可能会在信号spider_opened之后被发送,取决于spider的启动方式
engine_stopped
scrapy.signals.engine_stopped()
当scrapy引擎停止时发送该信号例如爬取结束
该信号支持返回deferreds
item_scraped
scrapy.signals.item_scrapped(item,response,spider)
当item被爬取,并通过Item Pipeline后没有被dropped时发送,该信号支持返回deferreds
参数:爬取到的item对象
爬取item的spider对象
提取item的response对象
item_dropped
scrapy.signals.item_dropped(item,exception,spider)
当item通过Item Pipeline,有些pipeline抛出DropItem异常,丢弃item时发送,该信号支持返回deferreds
参数:Item Pipeline丢弃的item
爬取item的spider对象
导致item被丢弃的异常,必须是DropItem的子类
spider_closed
scrapy.signals.spider_closed(spider,reason)
当某个spider被关闭时发送,该信号可以用来释放每个spider在spider_opened后占用的资源
该信号支持返回deferreds
参数:被关闭的spider对象
描述spider被关闭的原因的字符串。如果spider是由于完成爬取而被关闭,则其为‘finished '。如果spider是被引擎的close_spider方法所关闭,则其为调用该方法时的reason参数(默认为' cancelled ')。如果引擎被关闭比如输入Ctrl + C ,则为' shutdown'
spider_opened
scrapy.signals.spider_opened(spider)
当spider开始爬取时发送该信号。该信号支持返回deferreds
参数:开启的spider对象
spider_idle
scrapy.signals.spider_idle(spider)
当spider进入空闲状态时发送该信号。
空闲意味着:requests正在等待被下载
requests被调度
items正在item pipeline中处理
当该信号的所有处理器handler被调用后,如果spider仍然保持空闲状态,引擎将会关闭该spider。当spider被关闭后,spider_closed信号将被发送
可以在spider_idle处理器中调度某些请求来避免spider被关闭。该信号不支持返回deferreds
参数:空闲的spider对象
spider_error
scrapy.signals.spider_error(failure,response,spider)
当spider的回调函数产生错误时发送该信号
参数:以Twisted Failure对象抛出的异常
当异常被抛出时被处理的response对象
抛出异常的spider对象
request_scheduled
scrapy.signals.request_scheduled(request,spider)
当引擎调度一个request对象用于下载时,该信号被发送,该信号不支持返回deferreds
参数:到达调度器的request对象
产生该request的spider对象
response_received
scrapy.signals.response_received(response,request,spider)
当引擎从downloader获取一个新的response时发送该信号,该信号不支持返回deferreds
参数:接受的response对象
生成response的request对象
response对应的spider对象
response_downloaded
scrapy.siganls.response_downloaded(response,request,spider)
当一个HttpResponse被下载时,由downloader发送该信号,该信号不支持返回deferreds
参数:下载的response对象
生成response的request对象
response对应的spider对象
|
文章出处 https://www.cnblogs.com/fu-yong/p/9260252.html