简体   繁体   English

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

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

1>Python Asyncio is not running new coroutine using asyncio.run_coroutine_threadsafe. 1>Python Asyncio 没有使用 asyncio.run_coroutine_threadsafe 运行新的协程。 Below is the code testing performed on Mac.下面是在 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))      

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

2 2

2>The output is same when I run on a different executor also as shown below 2>当我在不同的执行器上运行时,输出也是一样的,如下所示
————————————————————————————————————— —————————————————————————————————————————

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

————————————————————————————————————— —————————————————————————————————————————
Sample code:示例代码:

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))    

———————————————————————————————— ———————————————————————————————————
Output:输出:
1 Future -- 1 未来——
2 2

From asyncio.run_coroutine_threadsafe :asyncio.run_coroutine_threadsafe

This function is meant to be called from a different OS thread than the one where the event loop is running此函数旨在从与运行事件循环的线程不同的操作系统线程调用

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()

The first snippet submits a coroutine to the event loop it is already running in. You don't need run_coroutine_threadsafe for that, you can just call asyncio.create_task .第一个代码段将一个协程提交到它已经在其中运行的事件循环中。 run_coroutine_threadsafe您不需要run_coroutine_threadsafe ,您只需调用asyncio.create_task As mentioned in the other answer, the idea with run_coroutine_threadsafe is that you run it from your sync code in order to submit a task to an event loop running in another thread.正如另一个答案中提到的, run_coroutine_threadsafe的想法是从同步代码运行它,以便将任务提交给在另一个线程中运行的事件循环。

The other problem is that you never give a chance to the task to execute, as you don't await anything in main() and use run_until_complete(main()) at top-level.另一个问题是,您永远不会给任务执行机会,因为您不会在main()等待任何内容并在顶层使用run_until_complete(main()) As a result, the code only runs the event loop until main() completes, not caring for the tasks it might have spawned in the background.因此,代码只运行事件循环直到main()完成,而不关心它可能在后台产生的任务。 To fix it, you should either await the spawned task or return it so it can be awaited from top-level.要修复它,您应该等待生成的任务或返回它以便可以从顶层等待它。

The second snippet submits a coroutine to a freshly created event loop that no one is running, so again the coroutine doesn't get a chance to execute.第二个代码段将协程提交到一个新创建的没有人运行的事件循环,因此协程再次没有机会执行。 To fix it, you should execute new_loop.run_forever in an separate thread.要修复它,您应该在单独的线程中执行new_loop.run_forever

Finally, the executor as set by set_default_executor doesn't serve to execute coroutines.最后,由set_default_executor设置的执行器不用于执行协程。 In asyncio (and other Python async frameworks) coroutines all run in a single thread, the one that runs the event loop.在 asyncio(和其他 Python 异步框架)中,协程都在单个线程中运行,该线程运行事件循环。 The execute concurrently through the virtue of await transferring control back to the event loop.通过await将控制权转移回事件循环的优点,并发执行。 The executor you've set serves to execute blocking code passed to run_in_executor .您设置的执行程序用于执行传递给run_in_executor阻塞代码。

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

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