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

时间:2019-12-22 11:19:16

标签: python python-asyncio

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

2 个答案:

答案 0 :(得分:1)

来自asyncio.run_coroutine_threadsafe

  

该功能旨在从与运行事件循环的操作系统线程不同的操作系统线程中调用

listCategories: Array<Categorie>;
projet = { };

setListCategories(listCategories) {
  console.log('listCategories:: ', listCategories);
  this.listCategories = listCategories;
}

答案 1 :(得分:1)

第一个代码段向其已经在其中运行的事件循环提交一个协程。您不需要run_coroutine_threadsafe,只需调用asyncio.create_task。如另一个答案中所述,使用run_coroutine_threadsafe的想法是,您可以通过 sync 代码运行它,以便将任务提交给在另一个线程中运行的事件循环。

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

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

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