menu LittleJake's Blog
color_lens
avatar
Jake Liu
Never Settle
creative commons by-nc-sa
hit
Category
keyboard_arrow_down

© 2023 LittleJake's Blog.

萌ICP备20223020号

记一次使用Python协程的坑

前言

目前在写的自制消息推送服务器用到了多线程的方式进行处理,现在想改为使用高效率的协程进行处理。

过程

目前在搜索的过程中找到两种EventLoop的协程执行方法:

第一种

import asyncio

async def do_something():
    pass

event_loop = asyncio.get_event_loop()
asyncio.set_event_loop(event_loop)
task = asyncio.ensure_future(do_something())
event_loop.run_until_complete(task) # 阻塞运行完自动停止loop

第二种

import asyncio

async def do_something():
    pass

event_loop = asyncio.get_event_loop()
asyncio.set_event_loop(event_loop)
task = asyncio.ensure_future(do_something())
event_loop.run_forever() # 运行完不自动停止loop,一直阻塞

坑点

  1. 如果需要不断给loop添加协程,第二种执行方式无效,效率会因为阻塞运行与正常执行无差;
  2. 如果需要不断给永久运行中的loop添加协程,第一种和第二种执行方式均无效;
  3. 每次通过 asyncio.ensure_futureevent_loop.create_task 添加进loop后,都需要重新运行loop;

个人理解的图像

个人理解

解决循环添加的问题

通过查找手册,发现使用方法asyncio.run_coroutine_threadsafe可以动态添加协程。

import asyncio
from threading import Thread

event_loop = asyncio.get_event_loop()

async def do_something():
    pass

def new_event_loop():
    event_loop.run_forever() # 线程内阻塞

t = Thread(target=new_event_loop).start()

for i in range(100):
    asyncio.run_coroutine_threadsafe(do_something(), loop=event_loop)

后记

网上给出一堆的协程示例代码也只是简单的固定任务运行,只字不提动态添加的情况也是挺有意思的现象,说不定文章都是抄袭的?

Buy me a beer
Jake Liu
Never Settle

Title: 记一次使用Python协程的坑

Author: Jake Liu

Origin:

Creative Commons License

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) For any re-post you must give appropriate credit.

文章遵循CC许可 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 转载请注明出处

Tag:python, 协程, 线程

评论区

Add a new comment.

Theme