版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yangxiaodong88/article/details/82022309
背景
上次类似的文章,只是展示了将阻塞函数变为了非阻塞。 今天又有一些领悟。 @run_on_executor 装饰器的作用, 不管是变为非阻塞还可以 像celery 一个执行异步任务。
1、 将阻塞函数转非阻塞 函数 并获取到值
from tornado.concurrent import run_on_executor
import time
import tornado.web
import tornado.gen
from concurrent.futures import ThreadPoolExecutor
from concurrent import futures
import asyncio
class LogicAsyTest():
# executor = ThreadPoolExecutor(1)
# executor = ThreadPoolExecutor(255)
# executor = ThreadPoolExecutor(200)
# executor = ThreadPoolExecutor(100)
executor = ThreadPoolExecutor()
def __init__(self):
pass
@tornado.gen.coroutine
def bb(self):
res = yield self.my_sleep()
return res
async def execute(self, base_url):
""" 这个方法是非常好的的"""
result = Result.result_success()
res = await self.bb() # 这个是正确的
result['content'] = res
# time.sleep(100)
OHHOLog.print_log("test result")
OHHOLog.print_log(result)
return result
async def async_execute(self, base_url):
result = await self.execute(base_url)
return result
@run_on_executor
def my_sleep(self):
# data = dict()
# data["name"] = "哈哈"
# success = self.introduce.add(data)
# return success
time.sleep(5)
return 5
在这个示例中, 将sleep 函数转为非阻塞的并且要回去到返回值
执行的结果现象就是整个协程的接口 会花费5秒, 5秒阻塞当前的协程的执行。
2、将阻塞函数变为非阻塞函数, 相当于异步 线程跑在后台。 就像celery 一样
from tornado.concurrent import run_on_executor
import time
import tornado.web
import tornado.gen
from concurrent.futures import ThreadPoolExecutor
from concurrent import futures
import asyncio
class LogicAsyTest4():
# executor = ThreadPoolExecutor(1)
# executor = ThreadPoolExecutor(255)
# executor = ThreadPoolExecutor(200)
# executor = ThreadPoolExecutor(100)
executor = ThreadPoolExecutor()
def __init__(self):
pass
@tornado.gen.coroutine
def bb(self):
res = yield self.my_sleep()
return res
async def execute(self, base_url):
""" 这个方法是非常好的的"""
result = Result.result_success()
self.my_sleep()
OHHOLog.print_log("test result")
OHHOLog.print_log(result)
return result
async def async_execute(self, base_url):
result = await self.execute(base_url)
return result
@run_on_executor
def my_sleep(self):
time.sleep(5)
OHHOLog.print_log("哈哈哈 mysleep")
return 5
运行结果现象是, 接口立马返回。后台新另起的线程会去跑my_sleep的程序。 不影响接口的向下执行和返回。 当不需要返回值的程序中就会执行这样的程序。调用方式
self.my_sleep()
不需要yied 获取值。 这样也是非阻塞, 释放了GIL
使用await 和不使用await 之间区别
from tornado.concurrent import run_on_executor
import time
import tornado.web
import tornado.gen
from concurrent.futures import ThreadPoolExecutor
from concurrent import futures
import asyncio
class LogicAsyTest4():
# executor = ThreadPoolExecutor(1)
# executor = ThreadPoolExecutor(255)
# executor = ThreadPoolExecutor(200)
# executor = ThreadPoolExecutor(100)
executor = ThreadPoolExecutor()
def __init__(self):
pass
@tornado.gen.coroutine
def bb(self):
res = yield self.my_sleep()
return res
# @tornado.gen.coroutine
# def bb(self):
# yield self.my_sleep()
async def execute(self, base_url):
""" 这个方法是非常好的的"""
result = Result.result_success()
# res = await self.bb() # 这个是正确的
# self.my_sleep()
# await self.bb() # 实验数据证明 这是使用await 需要获取到结果 就会阻塞当前的协程, 但不会阻塞主线程
self.bb() # 不需要await 获取结果 就不会阻塞当前协程 也就跟不会阻塞当前主线程不会影响 别的协程执行
# result['content'] = res
# time.sleep(5)
OHHOLog.print_log("test result")
OHHOLog.print_log(result)
return result
async def async_execute(self, base_url):
result = await self.execute(base_url)
return result
@run_on_executor
def my_sleep(self):
time.sleep(5)
OHHOLog.print_log("哈哈哈 mysleep")
return 5
对于 不需要返回值 类似于celery 的异步方法就不需要yield from 或者 await 驱动的 后面也咩有必要中间再加入一个方法。 不需要获取返回值直接调用 @run_on_executor 方法就可以了。不需要重建的协程。 像这种情况 通过测试 当需要返回着的时候 使用await 驱动协程获取返回值, 这个时候会阻塞当前的协程但是不会阻塞当前的主线程。 不用await 的话也就是不驱动拿到具体的值就直接像调用正常方法一样调用, 中间不要用协程(没有用, 还增加代码的执行之间)。