首页 > 解决方案 > 如何终止事件循环

问题描述

我在 django 视图中有以下代码来创建后台任务:

    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_in_executor(None, update_contacts, {
        'email': email,
        'access_token': g.tokens['access_token']
    })

最后我需要做些什么来“杀死”循环吗?关闭它等的正确方法是什么?

标签: pythonpython-3.xpython-asyncio

解决方案


您不需要首先启动任何事件循环。该concurrent.futures提供对执行程序的直接访问,并threading允许您启动单个线程:

# raw thread
import threading

background_task = threading.Thread(
    target=update_contacts, kwargs={
        'email': email,
        'access_token': g.tokens['access_token']
})
background_task.start()

# executor thread pool
from concurrent.futures import ThreadPoolExecutor

my_executor = ThreadPoolExecutor()
my_executor.submit(update_contacts, email=email, access_token=g.tokens['access_token'])

通常,Thread如果您只想启动一项任务而忘记它,那么 a 会更简单。如果你同时有许多小任务, AThreadPoolExecutor会更高效;它也可以用来自动等待几个任务的完成。

print('start at', time.time())
with ThreadPoolExecutor() as executor:
    executor.submit(time.sleep, 1)
    executor.submit(time.sleep, 1)
    executor.submit(time.sleep, 1)
    executor.submit(time.sleep, 1)
print('done at', time.time())  # triggers after all 4 sleeps have finished

主要目的loop.run_in_executor不是提供 ThreadPoolExecutor。它旨在弥合阻塞代码的执行器和非阻塞代码的事件循环之间的差距。没有后者,根本没有必要使用。asnycio

import time
import asyncio

def block(delay: float):
    print("Stop! Blocking Time!")
    time.sleep(delay)  # block the current thread
    print("Done! Blocking Time!")

async def nonblock(delay: float):
    print("Erm.. Non-Blocking Time!")
    await asyncio.sleep(delay)
    print("Done! Non-Blocking Time!")

async def multiblock(delay: float):
    loop = asyncio.get_event_loop()
    await asyncio.gather(  # await async natively and sync via executors
        nonblock(delay),
        loop.run_in_executor(None, block, delay),
        nonblock(delay),
        loop.run_in_executor(None, block, delay),
    )

asyncio.run(multiblock(1))

推荐阅读