pythonpython-asyncio

python asyncio: How to get two infinite (with while True) async functions running concurrently?


I need to have several functions running concurrently and infinitely. I plan to use asyncio for this, and, if possible, I want to avoid using event loop directly.

I tried this code:

import asyncio
import os


class Program:
    def __init__(self):
        self.files = os.listdir('data')
        self.last_file = ''
        self.history = []

    async def wait_new_file(self):
        await self._wait_new_file()

    def _wait_new_file(self):
        while True:
            checked_files = set(os.listdir('data'))
            if new_file := checked_files.difference(set(self.files)):
                print(f'{new_file = }')
                self.last_file = list(new_file)[0]
                self.files.append(list(new_file)[0])
                self.history.append(f'>>>{self.files[-1]}')
                print(f'{self.files = }')
            if deleted_file := set(self.files).difference(checked_files):
                print(f'{deleted_file = }')
                self.files.remove(list(deleted_file)[0])
                print(f'{self.files = }')
            if os.path.exists('stop'):
                print(self.history)
                return

    async def check_difference(self):
        await self._check_difference()

    def _check_difference(self):
        flip = True
        while True:
            if flip and os.path.exists('flip'):
                flip = False
                print('on')
            if not flip and not os.path.exists('flip'):
                flip = True
                print('off')
            if os.path.exists('stop'):
                return

    async def main(self):
        async with asyncio.TaskGroup() as tg:
            task_check_difference = tg.create_task(self.check_difference())
            task_monitor_files = tg.create_task(self.wait_new_file())

program = Program()
asyncio.run(program.main())

But with this, task_monitor_files is not doing any job, please tell what is wrong there?


Solution

  • Ur problem is the way ur using asyncio and await's

    In _wait_new_file and _check_difference methods, ur using while True loops, which is blocking some code. When you call await self._wait_new_file() or await self._check_difference(), the execution will be stuck in these loop's and never return.

    To fix this, you should make those methods async by using asyncio.sleep() instead of busy-waiting.

    Here's an better version of your code:

    import asyncio
    import os
    
    
    class Program:
        def __init__(self):
            self.files = os.listdir('data')
            self.last_file = ''
            self.history = []
    
        async def wait_new_file(self):
            while True:
                ... # ur code
                await asyncio.sleep(1)  # wait for 1 second before checking again
    
        async def check_difference(self):
            flip = True
            while True:
                ... # ur code
                await asyncio.sleep(1)  # wait for 1 second before checking again
    
        async def main(self):
            async with asyncio.TaskGroup() as tg:
                task_check_difference = tg.create_task(self.check_difference())
                task_monitor_files = tg.create_task(self.wait_new_file())
    
    program = Program()
    asyncio.run(program.main())
    

    Hope this will help you.