當Deferred遇上Thread Deferred不會自動實現將阻塞過程轉為非阻塞過程,雖然它已經有那樣的機制但還是要你去多走一步。要將阻塞過程轉為真正的非阻塞過程,那 只有借用線程。但至於線程調用你不用太擔心,twisted已為你準備好一個方便的用法。就是將Deferred綁在Thread上,這樣就有了deferToThread,味道不比牛奶加巧克力差。 deferToThread在twisted文檔的說明,洋墨水喝得比較少,就不照字面翻譯了。大概意思是將函數f放在線程裡並作為Deferred返回,args和kwargs是函數f的參數。也就是使用deferToThread返回的是一個帶線程的Deferred,並自動使用callback調用指定的函數f。相當於在線程中運行下面的代碼 d=defer.Deferred().addCallback(f) d.callback(result)
def deferToThread(f, *args, **kwargs): (source) Run a function in a thread and return the result as a Deferred. Parameters f The function to call.
*args positional arguments to pass to f.
**kwargs keyword arguments to pass to f.
Returns A Deferred which fires a callback with the result of f, or an errback with a twisted.python.failure.Failure if f throws an exception.
#!/usr/bin/env python
#coding=utf-8
from twisted.internet import protocol,reactor,defer
from twisted.internet.threads import deferToThread
from twisted.protocols import basic
import time,sys
syscode='big5'
class muProtocol(basic.LineReceiver):
def connectionMade(self):
print 'connectionMade'
self.factory.clients[self]={}
self.factory.clients[self]['isblankly']=True
def lineReceived(self,data):
self.factory.clients[self]['isblankly']=False
self.transport.write(self.factory.getSomething(data))
if data=='q':
self.transport.loseConnection()
self.factory.kungfuTea(data)
class muFactory(protocol.ServerFactory):
protocol=muProtocol
def __init__(self):
reactor.callLater(1,self.timeout)
self.clients={}
def timeout(self):
sys.stdout.write('.')
sys.stdout.flush()
reactor.callLater(1,self.timeout)
def getSomething(self,data):
return '\n\rServer say: %s\n\r' % data
def goodTaste(self,data):
print u'%s:耍下太極,仲加埋嘆下功夫茶,都有排等羅。'.encode(
syscode,'replace') % data
time.sleep(10)
print u'%s,打完收功。'.encode(syscode,'replace') % data
return data
def wrongTaste(self,data):
print u'%s:好味道盡在kung fu tea。'.encode(syscode,'replace') % data
def kungfuTea(self,data):
return deferToThread(self.goodTaste,data
).addBoth(self.wrongTaste)
reactor.listenTCP(20190,muFactory())
reactor.run()
分析下上面的代碼。 當接收到數據後調用self.factory.kungfuTea(data) def lineReceived(self,data): self.factory.kungfuTea(data) 工廠中的kungfuTea只是使用deferToThread將真正處理數據的過程轉goodTaste為一個線程的Deferred,剩下的東西就和Deferred操作無異。
牛奶加巧克力不錯,老板再來一杯!
原文 http://sites.google.com/site/mypynotes/twisted-1/defertothread