twisted中将阻塞函数非阻塞化
twisted FAQs已经明确表示“deferreds 不能够自动转换阻塞代码块成为非阻塞的”。那么,怎么才能够实现这个功能呢?下面介绍一个解决的方法!
python代码:
#=================start code=============================
#coding=gb2312
from twisted.internet import reactor, defer
from twisted.python import threadable; threadable.init(1)
import sys, time
## 错误的方式
def callInThread(func, *args):
"""Takes a blocking function an converts it into a deferred-valued
function running in a separate thread.
"""
de = defer.Deferred()
de.addCallback(func)
reactor.callInThread(de.callback, *args)
return de
deferred = callInThread.__get__ # decorator associated to callInThread
# 正确的方法
from twisted.internet.threads import deferToThread
deferred =3D deferToThread.__get__
## 测试代码
def print_(result):
print result
def running():
"Prints a few dots on stdout while the reactor is running."
sys.stdout.write("."); sys.stdout.flush()
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"
if __name__ =3D=3D "__main__":
sleep(2).addBoth(print_)
reactor.callLater(.1, running)
reactor.callLater(3, reactor.stop)
reactor.run()
#========end code===================
运行结果如下:
start sleep 2
..................
end sleep 2
ok
.........
可以看到:在sleep函数执行过程中,并没有阻塞掉其他函数的执行(打印“.”) 。
结论:
在使用twisted过程中,如何将阻塞块变成非阻塞是一个很普遍的问题。但是twisted文档并没有提供简单的解决方法。 在这个例子里面,是decorator刷了个魔术,将sleep由一个阻塞函数,变成为一个deferred函数。
总之一句话:任何时候当你有一个阻塞函数在你的代码里,将其用deferred包装起来然后你会发现:生活是多么美好!