简介

Django、Flask、scrapy都包含了一个“信号分配器”,使得当一些动作在框架的其他地方发生的时候,解耦的应用可以得到提醒。

通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者,这是特别有用的设计因为有些代码对某些事件是特别感兴趣的,比如删除动作。

下面,分别介绍一下三种信号的使用示例。

Django信号

很多数情况下,我们需要在操作数据库之前或者之后做某些操作,比如说写个日志之类的,我们当然可以找到每一个sql语句,在其前后加一段代码,

但是,这不但浪费时间,还为以后的维护增加了难度,这个时候,就体现出信号的作用了。下面的代码是Django中对数据库增加一条数据的操作:

  1. # models.py
  2.  
  3. from django.db import models
  4.  
  5. class User(models.Model):
  6. title = models.CharField(max_length=32)
  7.  
  8. # views.py
  9.  
  10. from django.shortcuts import render,HttpResponse
  11. from app01 import models
  12.  
  13. def func1(request):
  14. models.User.objects.create(title='付勇')
  15. return HttpResponse('创建成功')
  16.  
  17. def func2(request):
  18. models.User.objects.create(title='小男孩')
  19. return HttpResponse('创建成功')
  20.  
  21. def func3(request):
  22. models.User.objects.create(title='小少年')
  23. return HttpResponse('创建成功')
  24.  
  25. def func4(request):
  26. models.User.objects.create(title='小青年')
  27. return HttpResponse('创建成功')

 这个时候,如果我们想要在每增加一条数据之后在控制台打印一句话(当然可以换成其他操作)的话,就可以在项目下的__init__.py中进行信号操作,代码如下:

  1. from django.db.models import signals
  2.  
  3. def before_save1(*args,**kwargs):
  4. print('before_save1--->',args,kwargs)
  5.  
  6. def before_save2(*args,**kwargs):
  7. print('before_save2--->',args,kwargs)
  8.  
  9. def after_save1(*args,**kwargs):
  10. print('after_save2---->',args,kwargs)
  11.  
  12. # 在增加数据之前执行before_save1函数
  13. signals.pre_save.connect(before_save1)
  14.  
  15. # 在增加数据之前执行before_save2函数
  16. signals.pre_save.connect(before_save2)
  17.  
  18. # 在增加数据之后执行after_save1函数
  19. signals.post_save.connect(after_save1)

Django中的内置信号:

  1. Model signals
  2. pre_init # django的modal执行其构造方法前,自动触发
  3. post_init # django的modal执行其构造方法后,自动触发
  4. pre_save # django的modal对象保存前,自动触发
  5. post_save # django的modal对象保存后,自动触发
  6. pre_delete # django的modal对象删除前,自动触发
  7. post_delete # django的modal对象删除后,自动触发
  8. m2m_changed # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
  9. class_prepared # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
  10. Management signals
  11. pre_migrate # 执行migrate命令前,自动触发
  12. post_migrate # 执行migrate命令后,自动触发
  13. Request/response signals
  14. request_started # 请求到来前,自动触发
  15. request_finished # 请求结束后,自动触发
  16. got_request_exception # 请求异常后,自动触发
  17. Test signals
  18. setting_changed # 使用test测试修改配置文件时,自动触发
  19. template_rendered # 使用test测试渲染模板时,自动触发
  20. Database Wrappers
  21. connection_created # 创建数据库连接时,自动触发

Flask信号

项目功能复杂,代码量越大,就越需要做业务解耦。否则在其之上做开发和维护是很痛苦的,尤其是对于团队的新人。

Flask从0.6开始,通过Blinker提供了信号支持。信号就是在框架核心功能或者一些Flask扩展发生工作时所发送的通知,用于帮助你解耦应用。

如果需要在Flask中使用信号,需要先安装blinker组件:

  1. pip install blinker

使用信号代码如下:

  1. from flask import Flask,render_template
  2. from flask import signals
  3.  
  4. app = Flask(__name__)
  5.  
  6. def x1(arg):
  7. print('x1')
  8. def x2(arg):
  9. print('x2')
  10.  
  11. # 在发起请求之前执行x1函数
  12. signals.request_started.connect(x1)
  13. # 在发起请求之前执行x2函数
  14. signals.request_started.connect(x2)
  15.  
  16. @app.route('/index')
  17. def func():
  18. print('视图函数')
  19. return "ok"
  20.  
  21. if __name__ == '__main__':
  22. app.run()

Flask中内置的信号:

  1. 1. template_rendered:模版渲染完成后的信号。
  2.  
  3. 2. before_render_template:模版渲染之前的信号。
  4.  
  5. 3. request_started:模版开始渲染。
  6.  
  7. 4. request_finished:模版渲染完成。
  8.  
  9. 5. request_tearing_downrequest对象被销毁的信号。
  10.  
  11. 6. got_request_exception:视图函数发生异常的信号。一般可以监听这个信号,来记录网站异常信息。
  12.  
  13. 7. appcontext_tearing_downapp上下文被销毁的信号。
  14.  
  15. 8. appcontext_pushedapp上下文被推入到栈上的信号。
  16.  
  17. 9. appcontext_poppedapp上下文被推出栈中的信号
  18.  
  19. 10. message_flashed:调用了Flask`flashed`方法的信号。

Scrapy信号

Scrapy使用信号来通知事情发生。您可以在您的Scrapy项目中捕捉一些信号(使用 extension)来完成额外的工作或添加额外的功能,扩展Scrapy。

虽然信号提供了一些参数,不过处理函数不用接收所有的参数 - 信号分发机制(singal dispatching mechanism)仅仅提供处理器(handler)接受的参数。

使用的时候新建一个py文件,如ext.py,代码如下:

  1. from scrapy import signals
  2.  
  3. class MyExtend(object):
  4. def __init__(self):
  5. pass
  6.  
  7. @classmethod
  8. def from_crawler(cls, crawler):
  9. self = cls()
  10. # 爬虫启动的时候执行x1方法
  11. crawler.signals.connect(self.x1, signal=signals.spider_opened)
  12. # 爬虫启动的时候执行x2方法
  13. crawler.signals.connect(self.x2, signal=signals.spider_closed)
  14.  
  15. return self
  16.  
  17. def x1(self, spider):
  18. print('open')
  19.  
  20. def x2(self, spider):
  21. print('close')

Scrapy内置的信号:

  1. engine_started
  2.  
  3. scrapy.signals.engine_started()
  4.  
  5. scrapy引擎启动爬取时发送该信号
  6.  
  7. 该信号支持返回deferreds
  8.  
  9. 当信号可能会在信号spider_opened之后被发送,取决于spider的启动方式
  10.  
  11. engine_stopped
  12.  
  13. scrapy.signals.engine_stopped()
  14.  
  15. scrapy引擎停止时发送该信号例如爬取结束
  16.  
  17. 该信号支持返回deferreds
  18.  
  19. item_scraped
  20.  
  21. scrapy.signals.item_scrapped(item,response,spider)
  22.  
  23. item被爬取,并通过Item Pipeline后没有被dropped时发送,该信号支持返回deferreds
  24.  
  25. 参数:爬取到的item对象
  26.  
  27.    爬取itemspider对象
  28.  
  29.    提取itemresponse对象
  30.  
  31. item_dropped
  32.  
  33. scrapy.signals.item_dropped(item,exception,spider)
  34.  
  35. item通过Item Pipeline,有些pipeline抛出DropItem异常,丢弃item时发送,该信号支持返回deferreds
  36.  
  37. 参数:Item Pipeline丢弃的item
  38.  
  39.    爬取itemspider对象
  40.  
  41.    导致item被丢弃的异常,必须是DropItem的子类
  42.  
  43. spider_closed
  44.  
  45. scrapy.signals.spider_closed(spider,reason)
  46.  
  47. 当某个spider被关闭时发送,该信号可以用来释放每个spiderspider_opened后占用的资源
  48.  
  49. 该信号支持返回deferreds
  50.  
  51. 参数:被关闭的spider对象
  52.  
  53.    描述spider被关闭的原因的字符串。如果spider是由于完成爬取而被关闭,则其为‘finished'。如果spider是被引擎的close_spider方法所关闭,则其为调用该方法时的reason参数(默认为'cancelled')。如果引擎被关闭比如输入Ctrl + C ,则为'shutdown'
  54.  
  55. spider_opened
  56.  
  57. scrapy.signals.spider_opened(spider)
  58.  
  59. 当spider开始爬取时发送该信号。该信号支持返回deferreds
  60.  
  61. 参数:开启的spider对象
  62.  
  63. spider_idle
  64.  
  65. scrapy.signals.spider_idle(spider)
  66.  
  67. 当spider进入空闲状态时发送该信号。
  68.  
  69. 空闲意味着:requests正在等待被下载
  70.  
  71.       requests被调度
  72.  
  73.       items正在item pipeline中处理
  74.  
  75. 当该信号的所有处理器handler被调用后,如果spider仍然保持空闲状态,引擎将会关闭该spider。当spider被关闭后,spider_closed信号将被发送
  76.  
  77. 可以在spider_idle处理器中调度某些请求来避免spider被关闭。该信号不支持返回deferreds
  78.  
  79. 参数:空闲的spider对象
  80.  
  81. spider_error
  82.  
  83. scrapy.signals.spider_error(failure,response,spider)
  84.  
  85. 当spider的回调函数产生错误时发送该信号
  86.  
  87. 参数:以Twisted Failure对象抛出的异常
  88.  
  89.    当异常被抛出时被处理的response对象
  90.  
  91.    抛出异常的spider对象
  92.  
  93. request_scheduled
  94.  
  95. scrapy.signals.request_scheduled(request,spider)
  96.  
  97. 当引擎调度一个request对象用于下载时,该信号被发送,该信号不支持返回deferreds
  98.  
  99. 参数:到达调度器的request对象
  100.  
  101.    产生该request的spider对象
  102.  
  103. response_received
  104.  
  105. scrapy.signals.response_received(response,request,spider)
  106.  
  107. 当引擎从downloader获取一个新的response时发送该信号,该信号不支持返回deferreds
  108.  
  109. 参数:接受的response对象
  110.  
  111.    生成response的request对象
  112.  
  113.    response对应的spider对象
  114.  
  115. response_downloaded
  116.  
  117. scrapy.siganls.response_downloaded(response,request,spider)
  118.  
  119. 当一个HttpResponse被下载时,由downloader发送该信号,该信号不支持返回deferreds
  120.  
  121. 参数:下载的response对象
  122.  
  123.    生成response的request对象
  124.  
  125.     response对应的spider对象

  

信号(Django信号、Flask信号、Scrapy信号)的更多相关文章

  1. django 缓存、中间件、信号、CSRF 详解

    中间件 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法. 在django项 ...

  2. day20 FORM补充(随时更新),F/Q操作,model之多对多,django中间件,缓存,信号

    python-day20 1.FROM生成select标签的数据应该来源于数据库. 2.model 操作 F/Q  (组合查询) 3.model 多对多操作. 4.中间件 :在请求到达url前先会经过 ...

  3. Django 缓存、序列化、信号

    一,缓存 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcac ...

  4. WEB框架Django之中间件/缓存/CBV/信号

    一Djano的中间件 1 中间件的概念 中间件顾名思义,是介于request与respose处理之间的一道处理过程,相对比较轻量级,并且全局上改变django的输入与输出.因为改变是全局, 所有需要谨 ...

  5. Django进阶之缓存和信号

    一.缓存 简介 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者mem ...

  6. 第三百五十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy信号详解

    第三百五十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy信号详解 信号一般使用信号分发器dispatcher.connect(),来设置信号,和信号触发函数,当捕获到信号时执行 ...

  7. Python开发【Django】:缓存、信号

    缓存 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache ...

  8. Django组件补充(缓存,信号,序列化)

    Django组件补充(缓存,信号,序列化) Django的缓存机制 1.1 缓存介绍 1.缓存的简介 在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑 ...

  9. 三十四 Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy信号详解

    信号一般使用信号分发器dispatcher.connect(),来设置信号,和信号触发函数,当捕获到信号时执行一个函数 dispatcher.connect()信号分发器,第一个参数信号触发函数,第二 ...

随机推荐

  1. 与其他Javascript类库冲突解决方案

    $(document).ready(function() { var $jq = jQuery.noConflict(); $jq('#id').show(); });

  2. 【Latex】数学公式排版

    http://www.cnblogs.com/houkai/p/3399646.html 常用latex数学符号表 https://zh.wikipedia.org/wiki/Help:%E6%95% ...

  3. 【MongoDB】数组长度查询

    db.groupedInfo.count({'surveyInfo.surveyAndUserID.0':{$exists:1}})

  4. 转:windows 下 netsh 实现 端口映射(端口转发)

    本文转自:本文出自 “httpyuntianjxxll.spac..” 博客,请务必保留此出处http://333234.blog.51cto.com/323234/1135361 -----hapr ...

  5. 实操演练!MathType几个绝妙小技巧!

    在论文中编写公式时MathType绝对是很多人不二的选择,它的功能比较完善,操作比较方便,包含的符号模板很多,易学易上手,这些都是它的优点.但是在使用MathType时,还有很多绝妙的小技巧,使用起来 ...

  6. CSS3 经典教程系列:CSS3 圆角(border-radius)详解

    http://www.cnblogs.com/lhb25/archive/2013/01/30/css3-border-radius.html 特别好的一篇文章

  7. 而桌面app向来是web前端开发开发人员下意识的避开方

    web前端语言的发展有目共睹, 从原来的pc web, 到后来的mobile SAP, 再到 nodejs,全站工程师应运而生. js快速而且稳健的发展让人不得不重视, 相应的前端开发人员的地位也越来 ...

  8. Trie树(字典树)(1)

    Trie树.又称字典树,单词查找树或者前缀树,是一种用于高速检索的多叉树结构. Trie树与二叉搜索树不同,键不是直接保存在节点中,而是由节点在树中的位置决定. 一个节点的全部子孙都有同样的前缀(pr ...

  9. Effective C++ Item 14 Think carefully about copying behavior in resource-managing classe

    In C++, the only code that guaranteed to be executed after an exception is thrown are the destructor ...

  10. Android NDK开发-1-环境搭建

    1.NDK介绍 Android NDK 是在SDK前面又加上了“原生”二字,即Native Development Kit,因此又被Google称为“NDK”.众所周知,Android程序运行在Dal ...