Twisted 异步请求处理
我想知道怎么在Twisted里像在Node.js那样处理异步请求。
我写了一个Twisted的示例,但我的应用程序还是在等待一个长时间操作的结果(我用time.sleep来模拟这个过程)。
另外,我也不太明白怎么正确使用reactor.callLater。
这是我写的Twisted应用的示例。
from twisted.web import server
from twisted.web.resource import Resource
from twisted.internet import reactor
from twisted.internet.defer import Deferred
import time
class Hello(Resource):
def getChild(self, name, request):
if name == '':
return self
print name
return Resource.getChild(self, name, request)
def render_GET(self, req):
d = Deferred()
reactor.callLater(2, d.callback, None)
d.addCallback(lambda _: self.say_hi(req))
return server.NOT_DONE_YET
def say_hi(self, req):
req.setHeader("content-type", "text/html")
time.sleep(5)
req.write("hello!")
req.finish()
class Hello2(Resource):
isLeaf = True
def render_GET(self, req):
req.setHeader("content-type", "text/html")
return "hello2!"
root = Hello()
root.putChild("2", Hello2())
reactor.listenTCP(8080, server.Site(root))
reactor.run()
补充:现在我想问的是怎么写同步代码?请给个例子。
1 个回答
4
你其实已经在做了... 有点。
你遇到的问题是,time.sleep()
是一个阻塞调用,这会让你的整个服务器停下来。
如果你把它当作网络输入输出(I/O)操作的替代品(比如 urllib
),最好的选择通常是用 Twisted 来处理 I/O(比如 twisted.web.client.getPage
),而不是试图去处理这个阻塞的代码。Twisted 有很多客户端库,这些库通常会给你一个 Deferred
,你已经在处理这个了。
如果你把它当作真正等待的替代品,那么你可以创建一个 Deferred
,它会用 deferLater
来等待。
如果你把它当作一些 CPU 密集型的操作(比如 PIL 图像编码,或者一个本地的 XML 解析器),或者是一个现有的本地/专有 I/O 层(比如 Oracle 或 MSSQL 数据库绑定),你不想重写它来正确使用 Twisted,那么你可以用 deferToThread
来调用它。
无论你怎么得到你的 Deferred
,你几乎已经准备好处理它了。你只需要调整 say_hi
使其返回一个:
def say_hi(self, req):
req.setHeader("content-type", "text/html")
d = getADeferredSomehow()
def done(result):
req.write("hello!")
req.finish()
return d.addBoth(done)