如何在Python中实现类似Go Goroutine的函数并发执行?
问题:让Python异步函数实现类似Go Goroutine的并行运行
我有两个函数,希望它们能像Go语言的Goroutine一样并行运行,但当前代码并未实现并行。请注意,两个函数内部均无异步代码,且我需要使用它们的返回值进行后续操作。
原代码
import asyncio async def func1(i: int) -> int: print("Initiated func1") while i <= 100000000: i += 1 print("Finished func1") return 100 async def func2() -> (str, int): print("Initiated func2") return "hello world", 200 async def main(): res = await asyncio.gather(*(func1(10), func2())) return res if __name__ == "__main__": data1, data2 = asyncio.run(main()) print(f"func1: {data1}, func2: {data2}")
实际输出
Initiated func1 Finished func1 Initiated func2 func1: 100, func2: ('hello world', 200)
期望输出
Initiated func1 Initiated func2 Finished func1 func1: 100, func2: ('hello world', 200)
解决方案
问题根源
asyncio是单线程协作式异步框架,协程之间的切换依赖于可等待对象(比如await、asyncio.sleep())。原函数里全是同步阻塞代码(比如func1里的大循环),没有任何让出CPU的操作,导致事件循环只能先完整执行完func1,才会调度func2,自然没法实现并行。
修改方案
要让同步阻塞任务实现并行,需要把它们放到线程池或进程池中运行,这样不会阻塞asyncio的事件循环。以下是两种可行的实现方式:
方式1:使用asyncio.to_thread(Python 3.9+)
把原异步函数改成普通同步函数,用asyncio.to_thread将其包装成可并行执行的协程:
import asyncio def func1(i: int) -> int: print("Initiated func1") while i <= 100000000: i += 1 print("Finished func1") return 100 def func2() -> (str, int): print("Initiated func2") return "hello world", 200 async def main(): res = await asyncio.gather( asyncio.to_thread(func1, 10), asyncio.to_thread(func2) ) return res if __name__ == "__main__": data1, data2 = asyncio.run(main()) print(f"func1: {data1}, func2: {data2}")
方式2:使用loop.run_in_executor(兼容Python 3.7+)
通过线程池执行器手动调度同步任务:
import asyncio from concurrent.futures import ThreadPoolExecutor def func1(i: int) -> int: print("Initiated func1") while i <= 100000000: i += 1 print("Finished func1") return 100 def func2() -> (str, int): print("Initiated func2") return "hello world", 200 async def main(): loop = asyncio.get_running_loop() with ThreadPoolExecutor() as pool: res = await asyncio.gather( loop.run_in_executor(pool, func1, 10), loop.run_in_executor(pool, func2) ) return res if __name__ == "__main__": data1, data2 = asyncio.run(main()) print(f"func1: {data1}, func2: {data2}")
效果说明
修改后,两个同步函数会在独立的线程中并行执行,asyncio事件循环可以同时调度它们,最终输出会符合你的期望。
内容的提问来源于stack exchange,提问作者Gaurav Gupta
相关产品推荐
相关产品推荐

