剖析Python的Twisted框架的核心特性
一. reactor 二. twisted简单使用 # 示例一 twisted底层API的使用 from twisted.internet import reacto from twisted.internet import main from twisted.internet.interfaces import IReadDescriptor import socket class MySocket(IReadDescriptor): def __init__(self,address): # 连接服务器 self.address = address self.sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) self.sock.connect(address) self.sock.setblocking(0) # tell the Twisted reactor to monitor this socket for reading reactor.addReader(self) # 接口: 告诉reactor 监听的套接字描述符 def fileno(self): try: return self.sock.fileno() except socket.error: return -1 # 接口: 在连接断开时的回调 def connectionLost(self,reason): self.sock.close() reactor.removeReader(self) # 当应用程序需要终止时 调用: # reactor.stop() # 接口: 当套接字描述符有数据可读时 def doRead(self): bytes = '' # 尽可能多的读取数据 while True: try: bytesread = self.sock.recv(1024) if not bytesread: break else: bytes += bytesread except socket.error,e: if e.args[0] == errno.EWOULDBLOCK: break return main.CONNECTION_LOST if not bytes: return main.CONNECTION_DONE else: # 在这里解析协议并处理数据 print bytes 示例一可以很清晰的看到twisted的reactor本质:添加监听描述符,监听可读/可写事件,当事件来临时回调函数,回调完成之后继续监听事件。 三. twisted抽象 # 示例二 twisted抽象的使用 from twisted.internet import reactor from twisted.internet.protocol import Protocol,ClientFactory class MyProtocol(Protocol): # 接口: Protocols初始化时调用,并传入Transports # 另外 twisted会自动将Protocols的factory对象成员设为ProtocolsFactory实例的引用 # 如此就可以通过factory来与MyProtocolFactory交互 def makeConnection(self,trans): print 'make connection: get transport: ',trans print 'my factory is: ',self.factory # 接口: 有数据到达 def dataReceived(self,data): self.poem += data msg = 'Task %d: got %d bytes of poetry from %s' print msg % (self.task_num,len(data),self.transport.getPeer()) # 接口: 连接断开 def connectionLost(self,reason): # 连接断开的处理 class MyProtocolFactory(ClientFactory): # 接口: 通过protocol类成员指出需要创建的Protocols protocol = PoetryProtocol # tell base class what proto to build def __init__(self,address): self.poetry_count = poetry_count self.poems = {} # task num -> poem # 接口: 在创建Protocols的回调 def buildProtocol(self,address): proto = ClientFactory.buildProtocol(self,address) # 在这里对proto做一些初始化.... return proto # 接口: 连接Server失败时的回调 def clientConnectionFailed(self,connector,reason): print 'Failed to connect to:',connector.getDestination() def main(address): factory = MyClientFactory(address) host,port = address # 连接服务端时传入ProtocolsFactory reactor.connectTCP(host,port,factory) reactor.run() 示例二要比示例一要简单清晰很多,因为它无需处理网络IO,并且逻辑上更为清晰,实际上ClientFactory和Protocol提供了更多的接口用于实现更灵活强大的逻辑控制,具体的接口可参见twisted源代码。 四. twisted Deferred d = Deferred() # 添加正确回调和错误回调 d.addCallbacks(your_ok_callback,your_err_callback) # 添加公共回调函数 d.addBoth(your_common_callback) # 正确返回 将依次调用 your_ok_callback(Res) -> common_callback(Res) d.callback(Res) # 错误返回 将依次调用 your_err_callback(Err) -> common_callback(Err) d.errback(Err) # 注意,对同一个Defered对象,只能返回一次,尝试多次返回将会报错 twisted的defer是异步的一种变现方式,可以这么理解,他和thread的区别是,他是基于时间event的。 五.综合示例 下面的例子,你们自己跑跑,我上面说的都是一些个零散的例子,大家对照下面完整的,走一遍。 twisted理解其实却是有点麻烦,大家只要知道他是基于事件的后,慢慢理解就行了。 #coding:utf-8 #xiaorui.cc from twisted.internet import reactor,defer from twisted.internet.threads import deferToThread import os,sys from twisted.python import threadable; threadable.init(1) deferred =deferToThread.__get__ import time def todoprint_(result): print result def running(): "Prints a few dots on stdout while the reactor is running." # sys.stdout.write("."); sys.stdout.flush() print '.' reactor.callLater(.1,running) @deferred def sleep(sec): "A blocking function magically converted in a non-blocking one." print 'start sleep %s'%sec time.sleep(sec) print 'nend sleep %s'%sec return "ok" def test(n,m): print "fun test() is start" m=m vals = [] keys = [] for i in xrange(m): vals.append(i) keys.append('a%s'%i) d = None for i in xrange(n): d = dict(zip(keys,vals)) print "fun test() is end" return d if __name__== "__main__": #one sleep(10).addBoth(todoprint_) reactor.callLater(.1,running) reactor.callLater(3,reactor.stop) print "go go !!!" reactor.run() #two aa=time.time() de = defer.Deferred() de.addCallback(test) reactor.callInThread(de.callback,10000000,100 ) print time.time()-aa print "我这里先做别的事情" print de print "go go end" (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |