在 asyncio.gather() 中未调用而执行的 Asyncio 任务

Asyncio tasks executed without being called in asyncio.gather()

我想将一些处理程序方法放入字典并仅调用其中的一些方法(基于所需的处理程序)。但是,当 asyncio.gather() 执行时,所有任务都会执行。 这是代码片段:

import asyncio

class DataHandler():
    def __init__(self):
        pass

    async def generate_coroutines(self):
        all_handlers = {
            'handler1': asyncio.create_task(self.handler1()),
            'handler2': asyncio.create_task(self.handler2()),
            'handler3': asyncio.create_task(self.handler3()),
        }
        return all_handlers

    async def main(self, handlers):
        print('Main method started')

        all_handlers = await self.generate_coroutines()
        print('Handler coroutines created')

        # Only add the handlers that has been given as the argument
        required_handlers = []
        for handler in handlers:
            if handler in all_handlers.keys(): required_handlers.append(all_handlers[handler])

        output = list(await asyncio.gather(*required_handlers))
        print(output)


    async def handler1(self): 
        print('handler1 executed')
        return 'handler1_output'

    async def handler2(self):
        print('handler2 executed') 
        return 'handler2_output'

    async def handler3(self):
        print('handler3 executed') 
        return 'handler3_output'


if __name__ == '__main__':

    dh = DataHandler()
    loop = asyncio.get_event_loop()

    loop.run_until_complete( dh.main(['handler2']))

输出:

Main method started
Handler coroutines created
handler1 executed
handler2 executed
handler3 executed
['handler2_output']

期望的输出:

Main method started
Handler coroutines created
handler2 executed
['handler2_output']

如果我取消未使用的任务,则它们不会被执行。但是是不是可以创建所有可能的任务,只执行其中的一些,让其他的去(不需要取消其余的)

asyncio.create_task 创建 Task 在事件循环中安排协程。您可以通过延迟创建协程和 Task:

来解决此问题
class DataHandler():
    
    async def main(self, handlers):
        print('Main method started')
        
        # Only make coroutines from specified handlers
        required_coroutines = []
        for handler in handlers:
            if hasattr(self, handler): # directly check instance for handler
                required_coroutines.append(getattr(self, handler)())
        
        print('Handler coroutines created')

        output = list(await asyncio.gather(*required_coroutines))
        
        print(output)

    async def handler1(self): 
        print('handler1 executed')
        return 'handler1_output'

    async def handler2(self):
        print('handler2 executed') 
        return 'handler2_output'

    async def handler3(self):
        print('handler3 executed') 
        return 'handler3_output'

在您的原始代码中,handler2() 协程没有被 gather 安排第二次,因为协程不能安排超过一次。你必须每次都调用异步函数并创建一个新的协程。