我试图开发一个简单的扭曲矩阵示例,目的是执行函数的异步执行,但打印接缝告诉我执行是同步还是按顺序执行,我的误解在哪里?
from twisted.internet.defer import inlineCallbacks, returnValue
import time, random
def _print_(x):
print "BAR", x
@inlineCallbacks
def sqrt(x):
time.sleep(random.random())
r = yield x*2
print "FOO", r
returnValue(r)
if __name__=='__main__':
for dd in map(sqrt, range(10)):
dd.addCallback(_print_)
答案 0 :(得分:1)
Twisted不会将阻塞代码转换为非阻塞代码,也不会将同步代码转换为异步代码。它为您提供了编写异步代码的工具。
phpPgAdmin
与inlineCallbacks
基本相同,但使用不同的API。它并没有改变Twisted的单线程,协作多任务特性。
您按顺序发布的程序会在范围(10)的整数上调用sqrt。每次调用Deferred
都会随机休眠一段时间,然后计算结果。计算都发生在一个线程中,因此一次只能发生一件事。当睡眠发生时,没有别的。
您可以使用Twisted的助手之一替换阻止sqrt
来电:
time.sleep()
现在from twisted.internet.task import deferLater
from twisted.internet import reactor
@inlineCallbacks
def sqrt(x):
yield deferLater(reactor, random.random(), lambda: None)
r = yield x*2
print "FOO", r
returnValue(r)
不会阻止sqrt
来电。相反,它放弃了对反应堆的控制。 time.sleep()
返回一个deferLater(...)
,在给定的延迟后,将使用给定函数的结果为您触发(在这种情况下,函数是无关紧要的,因为您只想睡觉,但是Deferred
需要一些功能。)
结合deferLater
,这会给你一个"睡眠"没有阻塞反应堆线程。在时间过去之前,反应堆可以自由查找要处理的其他事件,直到inlineCallbacks
deferLater(...)
触发为止。当发生这种情况时,执行可以在Deferred
内恢复,计算可以继续进行。当然,请注意计算本身仍然是阻塞的。但是,由于它是一个简单的整数乘法,它可能不会长时间阻塞。
sqrt
解决方案特定于deferLater
。如果您有其他形式的阻止,您可能需要了解其他解决这些问题的API。