當Deferred遇上Thread

當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

发表评论

电子邮件地址不会被公开。 必填项已用*标注