zoukankan      html  css  js  c++  java
  • 信号(Django信号、Flask信号、Scrapy信号)

    简介

    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  
     9 # views.py
    10  
    11 from django.shortcuts import render,HttpResponse
    12 from app01 import models
    13  
    14 def func1(request):
    15     models.User.objects.create(title='付勇')
    16     return HttpResponse('创建成功')
    17  
    18 def func2(request):
    19     models.User.objects.create(title='小男孩')
    20     return HttpResponse('创建成功')
    21  
    22 def func3(request):
    23     models.User.objects.create(title='小少年')
    24     return HttpResponse('创建成功')
    25  
    26 def func4(request):
    27     models.User.objects.create(title='小青年')
    28     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  
    17 @app.route('/index')
    18 def func():
    19     print('视图函数')
    20     return "ok"
    21  
    22  
    23 if __name__ == '__main__':
    24     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_down:request对象被销毁的信号。
    10  
    11 6. got_request_exception:视图函数发生异常的信号。一般可以监听这个信号,来记录网站异常信息。
    12  
    13 7. appcontext_tearing_down:app上下文被销毁的信号。
    14  
    15 8. appcontext_pushed:app上下文被推入到栈上的信号。
    16  
    17 9. appcontext_popped:app上下文被推出栈中的信号
    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       爬取item的spider对象
     28  
     29    提取item的response对象
     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       爬取item的spider对象
     40  
     41    导致item被丢弃的异常,必须是DropItem的子类
     42  
     43 spider_closed
     44  
     45 scrapy.signals.spider_closed(spider,reason)
     46  
     47 当某个spider被关闭时发送,该信号可以用来释放每个spider在spider_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对象
  • 相关阅读:
    Linux 软件安装到哪里合适,目录详解
    python如何判断1个列表中所有的数据都是相等的?
    web接口开发基础知识-什么是web接口?
    MIME TYPE是什么?
    jenkins展示html测试报告(不使用html publisher)
    【转】Java虚拟机的JVM垃圾回收机制
    Map 排序
    sql in 和 exist的区别
    distinct和group by 去掉重复数据分析
    sql执行机制
  • 原文地址:https://www.cnblogs.com/zhaohuhu/p/9264204.html
Copyright © 2011-2022 走看看