【发布时间】:2022-03-15 18:30:14
【问题描述】:
在 Go 语言中,以非阻塞方式运行另一个任务非常简单。
import "net/http"
func Call(request http.Request) http.Response {
response := getResponse(request)
go doTask(request) // Non-blocking. No need to wait for result.
return response
}
func getResponse(request http.Request) http.Response {
// Do something synchronously here
return http.Response{}
}
func doTask(r http.Request) {
// Some task which takes time to finish
}
如何在 python 中实现这一点?
我试过这样:
import asyncio
import threading
from asyncio.events import AbstractEventLoop
loop: AbstractEventLoop
def initialize():
global loop
loop = asyncio.new_event_loop()
thread = threading.Thread(target=run_event_loop)
thread.start()
def run_event_loop():
loop.run_forever()
def call(request):
response = get_response(request)
# This should not block
asyncio.run_coroutine_threadsafe(do_task(request), loop)
return response
def get_response(r):
# Do something synchronously here
return 42
async def do_task(r):
# Some task which takes time to finish
return
这行得通,但有点麻烦。
此外,python 代码仅使用 一个 线程来执行任务,而 Go 自动将任务分派给多个进程(Kotlin 也是如此)。
有没有更好的办法?
【问题讨论】:
-
如果你需要运行一个非阻塞协程,你可以简单地使用
asyncio.create_task(coroutine())。这假设您在事件循环线程中运行,这就是使用 asyncio 的程序的结构。 -
线程不一定是事件循环线程,所以我不能简单地使用
create_task。我猜loop.run_in_executor是迄今为止我能选择的最佳选择。 -
你甚至需要 asyncio 和一般的 async 吗?如果您只想调用同步函数而不等待它们完成,
concurrent.futures是实现目标的更简单的方法。
标签: python python-asyncio coroutine