Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

run async while loop independently

Is it possible to run an async while loop independently of another one?

Instead of the actual code I isolated the issue I am having in the following example code

import asyncio, time

class Time:
    def __init__(self):
        self.start_time = 0

    async def dates(self):
        while True:
            t = time.time()
            if self.start_time == 0:
                self.start_time = t
            yield t
            await asyncio.sleep(1)

    async def printer(self):
        while True:

            print('looping') # always called

            await asyncio.sleep(self.interval)

    async def init(self):
        async for i in self.dates():
            if i == self.start_time: 
                self.interval = 3 
                await self.printer()
            print(i) # Never Called

loop = asyncio.get_event_loop()
t = Time()
loop.run_until_complete(t.init())

Is there a way to have the print function run independently so print(i) gets called each time?

What it should do is print(i) each second and every 3 seconds call self.printer(i)

Essentially self.printer is a separate task that does not need to be called very often, only every x seconds(in this case 3).

In JavaScript the solution is to do something like so setInterval(printer, 3000);

EDIT: Ideally self.printer would also be able to be canceled / stopped if a condition or stopping function is called

like image 817
user3064433 Avatar asked Jan 24 '18 18:01

user3064433


1 Answers

The asyncio equivalent of JavaScript's setTimeout would be asyncio.ensure_future:

import asyncio

async def looper():
    for i in range(1_000_000_000):
        print(f'Printing {i}')
        await asyncio.sleep(0.5)

async def main():
    print('Starting')
    future = asyncio.ensure_future(looper())

    print('Waiting for a few seconds')
    await asyncio.sleep(4)

    print('Cancelling')
    future.cancel()

    print('Waiting again for a few seconds')
    await asyncio.sleep(2)

    print('Done')

if __name__ == '__main__':
    asyncio.get_event_loop().run_until_complete(main())
like image 109
Blender Avatar answered Sep 26 '22 14:09

Blender