信号(Django信号、Flask信号、Scrapy信号)
简介
Django、Flask、scrapy都包含了一个“信号分配器”,使得当一些动作在框架的其他地方发生的时候,解耦的应用可以得到提醒。
通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者,这是特别有用的设计因为有些代码对某些事件是特别感兴趣的,比如删除动作。
下面,分别介绍一下三种信号的使用示例。
Django信号
很多数情况下,我们需要在操作数据库之前或者之后做某些操作,比如说写个日志之类的,我们当然可以找到每一个sql语句,在其前后加一段代码,
但是,这不但浪费时间,还为以后的维护增加了难度,这个时候,就体现出信号的作用了。下面的代码是Django中对数据库增加一条数据的操作:
# 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中进行信号操作,代码如下:
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中的内置信号:
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组件:
pip install blinker
使用信号代码如下:
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. 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,代码如下:
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内置的信号:
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对象
信号(Django信号、Flask信号、Scrapy信号)的更多相关文章
- django 缓存、中间件、信号、CSRF 详解
中间件 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法. 在django项 ...
- day20 FORM补充(随时更新),F/Q操作,model之多对多,django中间件,缓存,信号
python-day20 1.FROM生成select标签的数据应该来源于数据库. 2.model 操作 F/Q (组合查询) 3.model 多对多操作. 4.中间件 :在请求到达url前先会经过 ...
- Django 缓存、序列化、信号
一,缓存 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcac ...
- WEB框架Django之中间件/缓存/CBV/信号
一Djano的中间件 1 中间件的概念 中间件顾名思义,是介于request与respose处理之间的一道处理过程,相对比较轻量级,并且全局上改变django的输入与输出.因为改变是全局, 所有需要谨 ...
- Django进阶之缓存和信号
一.缓存 简介 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者mem ...
- 第三百五十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy信号详解
第三百五十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy信号详解 信号一般使用信号分发器dispatcher.connect(),来设置信号,和信号触发函数,当捕获到信号时执行 ...
- Python开发【Django】:缓存、信号
缓存 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache ...
- Django组件补充(缓存,信号,序列化)
Django组件补充(缓存,信号,序列化) Django的缓存机制 1.1 缓存介绍 1.缓存的简介 在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑 ...
- 三十四 Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy信号详解
信号一般使用信号分发器dispatcher.connect(),来设置信号,和信号触发函数,当捕获到信号时执行一个函数 dispatcher.connect()信号分发器,第一个参数信号触发函数,第二 ...
随机推荐
- Spring-Condition设置
为了满足不同条件下生成更为合适的bean,可以使用condition配置其条件.假如有一个bean,id为magicBean,只有当其具有magic属性时才生成,方法如下: javaConfig模式: ...
- Oracle从字符串资源中得到想要的数据分析
[oracle]从字符串资源中得到想要的数据分析需求:订单分析,按照游戏,帐号级别,游戏帐号职业,区服,价格区间分析各款交易数据走势 .目标:订单表(order)处理分析:订单中可以直接读到的标示有游 ...
- Unity对象查找
1. GameObject.Find 全局摄像机 全局画布 全局灯光 无法查找隐藏对象 ,效率低下,要用完全的路径来提升查找效率 2. transform.Find UI中全部使用此方法 可以查找 ...
- NodeJs生成SVG图形验证码
背景:短信接口有调用限制,如果受到恶意攻击,很容易就爆掉,所以需要一系列验证机制,后端采用签名加密的方式,而前端要做人机识别,有两个要求: 1)不能使用文本式的验证码,很简单就能拿到 2)所有验证逻辑 ...
- Leetcode: Best Time to Buy and Sell Stock I, II
思路: 1. 算法导论讲 divide and conquer 时, 讲到过这个例子. 书中的做法是先让 price 数组减去一个值, 然后求解最大连续子数组的和. 分治算法的复杂度为 o(nlogn ...
- mac 环境配置
安装homebrew 用于安装各种软件 eg:brew search qq 查看qq安装目录 brew install 复制刚刚查看到的目录安装qq 安装 oh my zsh 自动补全目录跳转 1.安 ...
- 【RF库Collections测试】Remove From Dictionary
Name:Remove From DictionarySource:Collections <test library>Arguments:[ dictionary | *keys ]Re ...
- Apache nutch1.5 & Apache solr3.6
第1章引言 1.1nutch和solr Nutch 是一个开源的.Java 实现的搜索引擎.它提供了我们运行自己的搜索引擎所需的全部工具. Solr 拥有像 web-services API 的独立的 ...
- openstack的glance、nova、cinder使用ceph做后端存储
块设备与 OPENSTACK 通过 libvirt 你可以把 Ceph 块设备用于 OpenStack ,它配置了 QEMU 到 librbd 的接口. Ceph 把块设备映像条带化为对象并分布到集群 ...
- poj_3168 平面扫描
题目大意 给定平面上N个矩形的位置(给出矩形的左下角和右上角的坐标),这些矩形有些会有重叠,且重叠只会出现矩形的边重合全部或部分,矩形的顶点重合,而不会出现一个矩形的顶点位于另一个矩形的内部. ...