【问题标题】:Asyncio tasks executed without being called in asyncio.gather()未在 asyncio.gather() 中调用的异步任务执行
【发布时间】:2021-10-23 07:58:24
【问题描述】:

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

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']

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

【问题讨论】:

    标签: python python-3.x asynchronous async-await python-asyncio


    【解决方案1】:

    asyncio.create_task 创建Tasks,在事件循环中调度协程。你可以通过延迟创建协程和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 安排第二次,因为不能多次安排协程。你必须每次调用异步函数并创建一个新的协程。

    【讨论】:

    • 感谢您的解决方案。这比我的方法实用得多。
    猜你喜欢
    • 2017-01-11
    • 1970-01-01
    • 2021-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多