Asyncio: Как очистить экземпляр класса в методе __del__, когда нам нужно использовать методы asyn c - PullRequest
1 голос
/ 26 марта 2020

Предположим, для очистки класса требуется асин * сопрограмма c:

import asyncio                                                                                                          

class AsyncClient:                                                                                                      

    async def do_something(self):                                                                                       
        print ('Doing something')                                                                                       
        await asyncio.sleep(1)                                                                                          
        print ('Something done')                                                                                        

    async def cleanup(self):                                                                                            
        print ('Starting cleanup')                                                                                      
        await asyncio.sleep(1)                                                                                          
        print ('Cleanup in progress 1/3')                                                                               
        await asyncio.sleep(1)                                                                                          
        print ('Cleanup in progress 2/3')                                                                               
        await asyncio.sleep(1)                                                                                          
        print ('Cleanup in progress 3/3')                                                                               

    def __del__(self):
        **CODE_HERE_SHOULD_CALL_CLEANUP**

Недопустимо использовать await в методах dunder.

Что следует добавить в __del__ метод, позволяющий выполнить очистку в этих двух ситуациях:

client = AsyncClient() 

async def main():                                                                                                                                                                                                        
    await client.do_something()                                                                                         

asyncio.run(main())

ИЛИ

async def main():                                                                                                       
    client = AsyncClient()                                                                                              
    await client.do_something()                                                                                         

asyncio.run(main())

Я попытался сделать следующее, которое работает для первого случая, но не второй случай (я воссоздаю al oop, если l oop больше не существует):

    def __del__(self):                                                                                                  
        print ('__del__()')                                                                                             
        try:                                                                                                            
            loop = asyncio.get_event_loop()                                                                             
        except RuntimeError:                                                                                            
            loop = asyncio.new_event_loop()                                                                             
            asyncio.set_event_loop(loop)                                                                                
            asyncio.run(self.cleanup())                                                                                 
            return                                                                                                      

        cleanup_task = loop.create_task(self.cleanup())

1 Ответ

1 голос
/ 26 марта 2020

Очистка не должна зависеть от того, когда (или если) вызывается __del__. Определите метод очистки и либо вызовите его явно, либо разрешите контекстному менеджеру вызывать его неявно для вас.

import asyncio

class AsyncClient:

    async def do_something(self):
        print ('Doing something')
        await asyncio.sleep(1)
        print ('Something done')

    async def cleanup(self):
        print ('Starting cleanup')
        await asyncio.sleep(1)
        print ('Cleanup in progress 1/3')
        await asyncio.sleep(1)
        print ('Cleanup in progress 2/3')
        await asyncio.sleep(1)
        print ('Cleanup in progress 3/3')

    async def __aenter__(self):
       return self

    async def __aexit__(self, *args):
        await self.cleanup()

Затем

client = AsyncClient()

async def main():
    await client.do_something()
    await client.cleanup()

asyncio.run(main())

или что-то типа

client = AsyncClient()

async def main():
    async with client:
        await client.do_something()

asyncio.run(main())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...