![](/img/trans.png)
[英]Python asyncio difference between loop.create_task and 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>當我在不同的執行器上運行時,輸出也是一樣的,如下所示
—————————————————————————————————————————
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.