簡體   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