Reputation: 389
I'm trying to developing a simple twisted matrix example with the aim to perform async execution of a function but the print seams to tell me the execution is in sync or in sequential order, where is my misunderstanding?
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_)
Upvotes: 2
Views: 330
Reputation: 48315
Twisted does not turn blocking code into non-blocking code nor synchronous code into asynchronous code. It gives you tools for writing asynchronous code.
inlineCallbacks
is essentially the same thing as Deferred
but with a different API. It doesn't change the single-threaded, cooperative multi-tasking nature of Twisted.
The program you've posted sequentially calls sqrt on the integers in range(10). Each call to sqrt
sleeps for a random amount of time and then computes a result. The computation all happens in a single thread and so only one thing can happen at a time. When the sleep is happening, nothing else is.
What you can do is use one of Twisted's helpers to replace the blocking time.sleep()
call:
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)
Now sqrt
does not block in a time.sleep()
call. Instead, it gives up control to the reactor. deferLater(...)
returns a Deferred
that will be fired for you after the given delay with the result of the given function (in this case the function is irrelevant since you only want to sleep, but deferLater
requires some function).
Combined with inlineCallbacks
, this gives you a "sleep" without blocking the reactor thread. The reactor is free to find other events to process while time is passing until it is time for the deferLater(...)
Deferred
to fire. When that happens, execution can resume inside sqrt
and the computation can proceed. Of course, note that the computation itself is still blocking. However, since it's a simple integer multiplication, it probably doesn't block for long enough to matter.
The deferLater
solution is specific to time.sleep
. If you have other forms of blocking, you may need to learn about other APIs which address them.
You may also want to read How do I add two integers together with Twisted?
Upvotes: 1