Django、Flask、scrapy都包含了一個「信號分配器」,使得當一些動做在框架的其餘地方發生的時候,解耦的應用能夠獲得提醒。html
通俗來說,就是一些動做發生的時候,信號容許特定的發送者去提醒一些接受者,這是特別有用的設計由於有些代碼對某些事件是特別感興趣的,好比刪除動做。sql
下面,分別介紹一下三種信號的使用示例。數據庫
不少數狀況下,咱們須要在操做數據庫以前或者以後作某些操做,好比說寫個日誌之類的,咱們固然能夠找到每個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 # 建立數據庫鏈接時,自動觸發
項目功能複雜,代碼量越大,就越須要作業務解耦。不然在其之上作開發和維護是很痛苦的,尤爲是對於團隊的新人。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項目中捕捉一些信號(使用 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對象