信號(Django信號、Flask信號、Scrapy信號)

簡介

Django、Flask、scrapy都包含了一個「信號分配器」,使得當一些動做在框架的其餘地方發生的時候,解耦的應用能夠獲得提醒。html

通俗來說,就是一些動做發生的時候,信號容許特定的發送者去提醒一些接受者,這是特別有用的設計由於有些代碼對某些事件是特別感興趣的,好比刪除動做。sql

下面,分別介紹一下三種信號的使用示例。數據庫

Django信號

不少數狀況下,咱們須要在操做數據庫以前或者以後作某些操做,好比說寫個日誌之類的,咱們固然能夠找到每個sql語句,在其先後加一段代碼,django

可是,這不但浪費時間,還爲之後的維護增長了難度,這個時候,就體現出信號的做用了。下面的代碼是Django中對數據庫增長一條數據的操做:flask

 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中進行信號操做,代碼以下:app

 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信號

項目功能複雜,代碼量越大,就越須要作業務解耦。不然在其之上作開發和維護是很痛苦的,尤爲是對於團隊的新人。scrapy

Flask從0.6開始,經過Blinker提供了信號支持。信號就是在框架核心功能或者一些Flask擴展發生工做時所發送的通知,用於幫助你解耦應用。ide

若是須要在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對象
相關文章
相關標籤/搜索