![](/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.