前言
也玩了蠻久的scrapy了浦旱,scrapy底層用到的twisted還是要學習一下的您访,了解原理能提高自己的技術水平的說
異步編程
如果在某程序的運行時透硝,能根據(jù)已經(jīng)執(zhí)行的指令準確判斷它接下來要進行哪個具體操作膀估,那它是同步程序棠众,反之則為異步程序撰豺。(無序與有序的區(qū)別)
大部分編程語言中對方法的調用是同步執(zhí)行的粪般。例如在線程執(zhí)行體內,即線程的調用函數(shù)中污桦,方法的調用就是同步執(zhí)行的亩歹。如果方法需要很長的時間來完成,比方說從Internet加載數(shù)據(jù)的方法凡橱,調用者線程將被阻塞直到方法調用完成小作。如果不希望調用被阻塞,異步方法調用 它通過使用一種立即返回的異步的變量方法并提供額外的方法來支持接受完成通知以及完成等待 以優(yōu)化改進長期運行的(同步)方法稼钩。
反應器模式 reactor pattern
反應器模式是一種為處理服務請求并發(fā)提交到一個或者多個服務處理程序的事件設計模式顾稀。當請求抵達后,服務處理程序使用解多路分配策略坝撑,然后同步地派發(fā)這些請求至相關的請求處理程序
看英文版意思可能更清楚點
The reactor design pattern "Design pattern (computer science)") is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers.
反應器模式一定至少有一個在一直循環(huán)處理傳入事件的loop
基本使用
原理上的東西在寫的時候可能更好的理解静秆,先寫個簡單的程序吧
from twisted.internet import reactor
reactor.run()
twisted 就是一個反應堆模式,reactor是事件循環(huán)巡李,而這正是twisted的核心抚笔,從文檔和一些資料中我們知道
1.Twisted的reactor只有通過調用reactor.run()來啟動。
2.reactor循環(huán)是在其開始的進程中運行侨拦,上面的代碼也就是運行在主進程中殊橙。
3.一旦啟動,就會一直運行下去。reactor就會在程序的控制下(或者具體在一個啟動它的線程的控制下)膨蛮。
4.reactor循環(huán)并不會消耗任何CPU的資源叠纹。
5.并不需要顯式的創(chuàng)建reactor,只需要引入就OK了敞葛。
最后一條需要解釋清楚誉察。在Twisted中,reactor是單例模式制肮,即在一個程序中只能有一個reactor冒窍,并且只要你引入它就相應地創(chuàng)建一個。
接下來就可以跑一個twisted的hello world
from twisted.internet import reactor
def hello():
print("hello world")
reactor.callWhenRunning(hello)
reactor.run()
hello 方法就是我們說的回調方法了豺鼻,reactor 不需要知道回調方法的細節(jié)综液,只需要知道是哪個回調方法
1.reactor模式是單線程的。
2.像Twisted這種交互式模型已經(jīng)實現(xiàn)了reactor循環(huán)儒飒,意味無需我們親自去實現(xiàn)它谬莹。
3.我們仍然需要框架來調用我們自己的代碼來完成業(yè)務邏輯。
4.因為在單線程中運行桩了,要想跑我們自己的代碼附帽,必須在reactor循>環(huán)中調用它們。
5.reactor事先并不知道調用我們代碼的哪個函數(shù)
接下來寫一個定時關閉reactor的例子
from twisted.internet import reactor
def hello():
print("hello world")
def count(i):
print(i)
if i==5:
reactor.stop()
else:
reactor.callLater(1,count,i+1)
reactor.callWhenRunning(hello)
reactor.callWhenRunning(count,1)
reactor.run()
print("reactor down")
上面這個程序蕉扮,會在5s后關閉reactor,代碼里使用了callLater函數(shù)為Twisted注冊了一個回調函數(shù) 颗圣,api可以查看文檔twisted ReactorBase文檔
有一個很好的地方就是twisted 里面做好了錯誤異常處理喳钟,如果回調函數(shù)里面有exception,twisted會捕捉到了并輸出日志(所以scrapy spider中parse response的方法里面有錯在岂,也只會輸出錯誤堆棧奔则,而不會讓爬蟲掛掉)
結語
下一篇計劃寫下 twisted 的defer
先大體看下
異步編程中,defer機制主要是用來管理callback函數(shù)蔽午,在twisted中易茬,許多功能的實現(xiàn)都是采用的事件驅動機制,在異步編程中及老,錯誤處理機制和同步程序并不一樣抽莱,異步程序會無視錯誤執(zhí)行下去。在異步程序中處理錯誤顯得十分重要骄恶。defer就是來可以幫助我們來管理我們的callback和errback函數(shù)岸蜗。合理的安排defer在異步編程中顯得十分重要。