1.参考nonebot的run_sync的方法:
import asyncio
from functools import partial, wraps
import time
def run_sync(call):
"""一个用于包装 sync function 为 async function 的装饰器
参数:
call: 被装饰的同步函数
"""
@wraps(call)
async def _wrapper(*args, **kwargs):
loop = asyncio.get_running_loop()
pfunc = partial(call, *args, **kwargs)
result = await loop.run_in_executor(None, pfunc)
return result
return _wrapper
s = time.time()
@run_sync
def p_secs(secs):
print(f"{secs} start after begin {time.time()-s}s")
time.sleep(secs)
print(f"{secs} end after begin {time.time()-s}")
return 0
# 创建一个协程并启动
task = [p_secs(10),p_secs(2),p_secs(6)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(*task))
loop.close()
一般来说上面的输出如下
10 start after begin 0.004033803939819336s
2 start after begin 0.004033803939819336s
6 start after begin 0.004033803939819336s
2 end after begin 2.0071911811828613
6 end after begin 6.00560998916626
10 end after begin 10.018727540969849
使用修饰器快速打包sync函数到另外的一个线程执行,
避免io等待的操作阻塞主线程。
2.在py[3.9]版本使用to_thread
创建线程
3.9 新版功能.->协程与任务-to_thread
由于 GIL 的存在,asyncio.to_thread() 通常只能被用来将 IO 密集型函数变为非阻塞的。 但是,对于会释放 GIL 的扩展模块或无此限制的替代性 Python 实现来说,asyncio.to_thread() 也可被用于 CPU 密集型函数。
import asyncio
import time
s = time.time()
def sleep_secs(secs=3):
time.sleep(secs)
async def p_secs(secs):
print(f"{secs} start after begin {time.time()-s}s")
# await asyncio.gather(asyncio.to_thread(sleep_secs(secs)))
await asyncio.gather(
asyncio.to_thread(sleep_secs,secs),
asyncio.sleep(0.1))
print(f"{secs} end after begin {time.time()-s}")
# task = [p_secs(3),p_secs(2),p_secs(6)]
# asyncio.run(p_secs(3))
# 创建一个协程并启动
task = [p_secs(3),p_secs(2),p_secs(6),p_secs(9),p_secs(4),p_secs(1)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(*task))
loop.close()
一般来说上面的输出如下
3 start after begin 0.009048700332641602s
2 start after begin 0.010601520538330078s
6 start after begin 0.010601520538330078s
9 start after begin 0.010601520538330078s
4 start after begin 0.010601520538330078s
1 start after begin 0.010601520538330078s
1 end after begin 1.0323760509490967
2 end after begin 2.0214357376098633
3 end after begin 3.0332844257354736
4 end after begin 4.022623777389526
6 end after begin 6.034776926040649
9 end after begin 9.032061576843262
更为简单,高效的方法