使用tornado的coroutine进行编程

2022-01-23 0 1,138

在tornado3公布以后,加强了coroutine的定义,在异步编程中,取代了以前的gen.engine, 变为如今的gen.coroutine。这一装饰器原本便是为了更好地简单化在tornado中的异步编程。防止写调用函数, 促使开发设计起來更为合乎一切正常思维逻辑。一个简便的事例如下所示:

class MaindHandler(web.RequestHandler):

   @asynchronous

   @gen.coroutine

   def post(self):

       client = AsyncHTTPClient()

       resp = yield client.fetch(https://api.github.com/users")

       if resp.code == 200:

           resp = escape.json_decode(resp.body)

           self.write(json.dumps(resp, indent=4, separators=(',', ':')))

       else:

           resp = {"message": "error when fetch something"}

           self.write(json.dumps(resp, indent=4, separators={',', ':')))

       self.finish()

在yield句子以后,ioloop可能申请注册该事情,直到resp回到以后执行。这一环节是多线程的。在这儿应用json.dumps,而沒有应用tornado内置的escape.json_encode,是由于在搭建REST设计风格的API的情况下,通常会从电脑浏览器里浏览获得JSON文件格式的数据信息。应用json.dumps格式化数据信息以后,在电脑浏览器端表明查询的过程中会更为友善。Github API便是这一特点的使用人。实际上escape.json_encode便是对json.dumps的简易包裝,我还在提pull request规定包裝更多用途的情况下,创作者的回应escape并不准备给予所有的json作用,使用人可以自身立即应用json控制模块。

Gen.coroutine基本原理

在以前一篇blog中讲到要应用tornado的多线程特点,务必应用多线程的库。不然单独过程堵塞,压根不可能做到多线程的实际效果。 Tornado的多线程库文件最经常使用的便是内置的AsyncHTTPClient,及其在其基本上完成的OpenID登录认证插口。此外大量的多线程库可以这里寻找。包含用的比较多的MongoDB的Driver。

在3.0版本号以后,gen.coroutine控制模块看起来非常明显。coroutine装饰器可以让原本靠调整的异步编程看上去像同歩程序编写。在其中就是运用了Python中制作器的Send函数公式。在制作器中,yield关键词通常会与一切正常函数公式中的return对比。它可以被当做迭代器,进而应用next()回到yield的結果。可是制作器也有此外一个使用方法,便是应用send方式。在制作器內部可以将yield的結果取值给一个自变量,而这些值是根据外界的制作器client来send的。举一个事例:

def test_yield():

   pirnt "test yeild"

   says = (yield)

   print says

if ._name__ == "._main__":

   client = test_yield()

   client.next()

   client.send("hello world")

导出結果如下所示:

test yeild

hello world

早已在运作的变量会挂起来,直到读取它的client应用send方式,原先函数公式再次运作。而这儿的gen.coroutine方式便是多线程实行需求的实际操作,随后等候結果回到以后,再send到原函数,原函数则会执行,那样就以关联方法写的编码做到了多线程实行的实际效果。

Tornado异步编程

应用coroutine完成函数公式分离出来的异步编程。详细如下:

@gen.coroutine

def post(self):

   client = AsyncHTTPClient()

   resp = yield client.fetch("https://api.github.com/users")

   if resp == 200:

       body = escape.json_decode(resy.body)

   else:

       body = {"message": "client fetch error"}

       logger.error("client fetch error %d, %s" % (resp.code, resp.message))

   self.write(escape.json_encode(body))

   self.finish()

换为函数公式以后可以变为那样;

@gen.coroutime

def post(self):

   resp = yield GetUser()

   self.write(resp)

@gen.coroutine

def GetUser():

   client = AsyncHTTPClient()

   resp = yield client.fetch("https://api.github.com/users")

   if resp.code == 200:

       resp = escape.json_decode(resp.body)

   else:

       resp = {"message": "fetch client error"}

       logger.error("client fetch error %d, %s" % (resp.code, resp.message))

   raise gen.Return(resp)

这儿,当把多线程封装形式在一个函数公式中的情况下,并非像普通程序那般应用return关键词开展回到,gen控制模块给予了一个gen.Return的方式。是根据raise方式完成的。这一也是和它是应用制作器方法完成相关的。

应用coroutine跑计划任务

Tornado中有那么一个方式:

tornado.ioloop.IOLoop.instance().add_timeout()

该方式 是time.sleep的非堵塞版本号,它接纳一个時间长短和一个函数公式这两个主要参数。表明是多少時间以后读取该函数公式。在这儿它是根据ioloop的,因而是是非非堵塞的。该方式在手机客户端长连接及其调用函数程序编写中采用的比较多。可是用它来跑一些计划任务则是无奈之举。通常跑计划任务也没必要应用到它。可是我还在应用heroku的情况下,发觉未注册银行信用卡得话只是可以应用一个简易Web Application的代管。不可以加上计划任务来跑。因此就想到那么一个方式。在这儿,我关键应用它隔一段时间根据Github API插口去爬取数据信息。大自操作方法如下所示:

装饰器

 def sync_loop_call(delta=60 * 1000):

 """

 Wait for func down then process add_timeout

 """

     def wrap_loop(func):

         @wraps(func)

         @gen.coroutine

         def wrap_func(*args, **kwargs):

             options.logger.info("function %r start at %d" %

                                 (func.._name__, int(time.time())))

             try:

                 yield func(*args, **kwargs)

             except Exception, e:

                 options.logger.error("function %r error: %s" %

                                      (func.._name__, e))

             options.logger.info("function %r end at %d" %

                                 (func.._name__, int(time.time())))

             tornado.ioloop.IOLoop.instance().add_timeout(

                 datetime.timedelta(milliseconds=delta),

                 wrap_func)

         return wrap_func

     return wrap_loop

每日任务函数公式

 @sync_loop_call(delta=10 * 1000)

 def worker():

     """

     Do something

     """

加上每日任务

 if ._name__ == "._main__":

 worker()

 app.listen(options.port)

 tornado.ioloop.IOLoop.instance().start()

那样做以后,当Web Application运行以后,计划任务便会伴随着跑起来,并且因为它是根据事情的,而且多线程实行的,因此并不会危害Web服务的一切正常运作,自然每日任务不可以是堵塞的或测算密集式的。我这里主要是爬取数据信息,并且用的是Tornado内置的多线程爬取方式。

在sync_loop_call装饰器中,我还在wrap_func函数公式上加了@gen.coroutine装饰器,那样就确保仅有yeild的函数公式实行完以后,才会实行add_timeout实际操作。要是没有@gen.coroutine装饰器。那麼不直到yeild回到,便会实行add_timeout了。

详细地事例可以参照我的Github,这一新项目构建在heroku上。用以展现Github客户人气值排行和客户地区遍布状况。可以浏览Github-Data查询。因为中国heroku网站被封,必须越墙才可以浏览。

汇总

Tornado是一个非堵塞的web服务器及其web框架,可是在采用的情况下仅有应用多线程的库才会真真正正充分发挥它多线程的优点,自然有一些情况下由于App自身规定并非很高,要不是堵塞尤其比较严重得话,也不会有什么问题。此外应用coroutine控制模块开展异步编程的情况下,当把一个作用封装形式到一个函数公式里时,在函数公式运作中,即使发生不正确,要是没有去捕获得话也不会抛出去,这在调节上看起来十分艰难。

:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可, 转载请附上原文出处链接。
1、本站提供的源码不保证资源的完整性以及安全性,不附带任何技术服务!
2、本站提供的模板、软件工具等其他资源,均不包含技术服务,请大家谅解!
3、本站提供的资源仅供下载者参考学习,请勿用于任何商业用途,请24小时内删除!
4、如需商用,请购买正版,由于未及时购买正版发生的侵权行为,与本站无关。
5、本站部分资源存放于百度网盘或其他网盘中,请提前注册好百度网盘账号,下载安装百度网盘客户端或其他网盘客户端进行下载;
6、本站部分资源文件是经压缩后的,请下载后安装解压软件,推荐使用WinRAR和7-Zip解压软件。
7、如果本站提供的资源侵犯到了您的权益,请邮件联系: 442469558@qq.com 进行处理!

猪小侠源码-最新源码下载平台 Python教程 使用tornado的coroutine进行编程 http://www.20zxx.cn/295618/xuexijiaocheng/python.html

猪小侠源码,优质资源分享网

常见问题
  • 本站所有资源版权均属于原作者所有,均只能用于参考学习,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,建议提前注册好百度网盘账号,使用百度网盘客户端下载
查看详情

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务