Pause all asyncio tasks in Python

Question:

I have some asyncio tasks and I need to pause all of them.
This is my part of code:

import asyncio
import random


async def workers1():
    while True:
        k = random.randint(100, 200)
        await asyncio.sleep(k)
        await my_print(k)


async def workers2():
    while True:
        k = random.randint(100, 200)
        await asyncio.sleep(k)
        await my_print(k)


async def my_print(k):
    print(k)
    if k == 122:
        >>>>>>> suspend all of workers
        while k != 155:
            k = await repair()
            await asyncio.sleep(1)
        r>>>>>> resume all of workers

async def main():
    tasks = [asyncio.create_task(workers1()),
             asyncio.create_task(workers2())
             ]
    [await x for x in tasks]


if __name__ == '__main__':
    asyncio.run(main())

How can I suspend all of workers in my code when trouble happens in a function my_print and after repair in my_print resume all of tasks?

I will be glad if you give an example.
I have been seen this link. But that’s not what I need.

Asked By: dmitry123321

||

Answers:

Simply replace your call to await asyncio.sleep(1) with time.sleep(1). If your code doesn’t have an await expression in it, all the other tasks are effectively blocked.

import asyncio
import random
import time


async def workers1():
    while True:
        k = random.randint(100, 200)
        await asyncio.sleep(k)
        await my_print(k)
        
        
async def workers2():
    while True:
        k = random.randint(100, 200)
        await asyncio.sleep(k)
        await my_print(k)
        
        
async def my_print(k):
    print(k)
    if k == 122:
        >>>>>>> suspend all of workers
        while k != 155:
            k = random.randint(100, 200)
            time.sleep(1.0)  # CHANGE HERE
        r>>>>>> resume all of workers
    
async def main():
    tasks = [asyncio.create_task(workers1()), 
             asyncio.create_task(workers2())
             ]
    [await x for x in tasks]
    
    
if __name__ == '__main__':
    asyncio.run(main())
Answered By: Paul Cornelius

So, first, note that the time.sleep trick can be replaced with any non-asynchronous code. So you can do anything that runs synchronously instead of time.sleep.
Including set up a second asyncio loop in a different thread and run tasks in that loop.
The following code uses ThreadPoolExecutor from concurrent.futures to set up a new event loop. In particular:

    future = executor.submit(asyncio.run, task_3())

Will set up a new thread and run task_3 in that new loop.
The next line future.result() blocks the entire first loop (task_1 and task_2) until task_3 exits.
In task_3 you can do any asyncio operations you like, and until that exits all of the existing tasks will be suspended.

import asyncio, concurrent.futures

async def task_1():
    while True:
        print('task 1 runs')
        await asyncio.sleep(1)

async def task_2():
        print('task 2 starts')
        await asyncio.sleep(5)
        print('first set of tasks suspends')
        future = executor.submit(asyncio.run, task_3())
        print('suspending existing tasks')
        future.result()
        print('resuming tasks')
        

async def task_3():
    print('task 3 runs')
    await asyncio.sleep(4)
    print('task 3 finishes')

async def main():
    asyncio.ensure_future(task_1())
    asyncio.ensure_future(task_2())
    await asyncio.sleep(15)
    
executor = concurrent.futures.ThreadPoolExecutor()

asyncio.run(main())

Answered By: Sam Hartman
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.