繁体   English   中英

Python Asyncio 没有使用 asyncio.run_coroutine_threadsafe 运行新的协程

[英]Python Asyncio is not running new coroutine using asyncio.run_coroutine_threadsafe

1>Python Asyncio 没有使用 asyncio.run_coroutine_threadsafe 运行新的协程。 下面是在 Mac 上执行的代码测试。
———————————————————————————————————

import os    
import random      
import asyncio      
import logging     
from concurrent.futures import ThreadPoolExecutor      

os.environ['PYTHONASYNCIODEBUG'] = '1'      
logging.basicConfig(level=logging.WARNING)      

async def coro():      
    print("Coroutine {} is has started")      


async def main(loop):     
    print(" 1 ")    
    fut = asyncio.run_coroutine_threadsafe(coro(), loop)      
    print(f"Future  --")          
    print(" 2 ")      
    print(" Result ",fut.result())      
    print(" 3 ")      

if __name__== '__main__':      
    loop = asyncio.get_event_loop()      
    loop.set_debug(True)      
    loop.run_until_complete(main(loop))      

———————————————————————————————————
输出:
1
未来 -

2

2>当我在不同的执行器上运行时,输出也是一样的,如下所示
—————————————————————————————————————————

new_loop = asyncio.new_event_loop()      
new_loop.set_default_executor(ThreadPoolExecutor(max_workers=2))      
fut = asyncio.run_coroutine_threadsafe(coro(), new_loop) 

—————————————————————————————————————————
示例代码:

import os      
import random      
import asyncio      
import logging      
from concurrent.futures import ThreadPoolExecutor      

os.environ['PYTHONASYNCIODEBUG'] = '1'      
logging.basicConfig(level=logging.WARNING)      

async def coro():      
    print("Coroutine {} is has started")      


async def main(loop):    
    print(" 1 ")    
    new_loop = asyncio.new_event_loop()    
    new_loop.set_default_executor(ThreadPoolExecutor(max_workers=2))    
    fut = asyncio.run_coroutine_threadsafe(coro(), new_loop)      
    print(f"Future  --")        
    print(" 2 ")      
    print(" Result ",fut.result())      
    print(" 3 ")      

if __name__== '__main__':      
    loop = asyncio.get_event_loop()    
    loop.set_debug(True)      
    loop.run_until_complete(main(loop))    

———————————————————————————————————
输出:
1 未来——
2

asyncio.run_coroutine_threadsafe

此函数旨在从与运行事件循环的线程不同的操作系统线程调用

async def coro():
    print("Coroutine {} is has started")

def start_coro(loop):
    fut = asyncio.run_coroutine_threadsafe(coro(), loop)
    print(fut.result())

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.set_debug(True)
    Thread(target=start_coro, args=(loop,)).start()
    loop.run_forever()

第一个代码段将一个协程提交到它已经在其中运行的事件循环中。 run_coroutine_threadsafe您不需要run_coroutine_threadsafe ,您只需调用asyncio.create_task 正如另一个答案中提到的, run_coroutine_threadsafe的想法是从同步代码运行它,以便将任务提交给在另一个线程中运行的事件循环。

另一个问题是,您永远不会给任务执行机会,因为您不会在main()等待任何内容并在顶层使用run_until_complete(main()) 因此,代码只运行事件循环直到main()完成,而不关心它可能在后台产生的任务。 要修复它,您应该等待生成的任务或返回它以便可以从顶层等待它。

第二个代码段将协程提交到一个新创建的没有人运行的事件循环,因此协程再次没有机会执行。 要修复它,您应该在单独的线程中执行new_loop.run_forever

最后,由set_default_executor设置的执行器不用于执行协程。 在 asyncio(和其他 Python 异步框架)中,协程都在单个线程中运行,该线程运行事件循环。 通过await将控制权转移回事件循环的优点,并发执行。 您设置的执行程序用于执行传递给run_in_executor阻塞代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM