PayadorPerseguido
PayadorPerseguido

Reputation: 21

Is it possible to iterate a list calling async function

I'm new to this so I apologize for mistakes

I'm trying to figure out a way to iterate inside a for loop range, calling an async function but without waiting for a response

here's my code

import asyncio
from random import randint
import time
import threading

async def print_i(i):
   number = 0 
   if (number % 2) == 0: #check for even number
      time.sleep(5)
   while number != 5:
      number = randint(0,100)
   print("id-", i)

for i in range (0,100):
   asyncio.run(print_i(i))
   # thread = threading.Thread(target=print_i(i))
   # thread.start()
 

Both the asyncio.run and the thread.start() are linearly executing the called function, whereas i was hoping that the for loop would call the functions in all iterations in one go, and only the even numbers of "i" would get the time.sleep(5)

Is this possible?

Upvotes: 1

Views: 5255

Answers (1)

jupiterbjy
jupiterbjy

Reputation: 3503

Here's some basic examples I made about how to achieve concurrency in asyncio, threading, and trio. Consider range() call as list in these cases.

If you wonder why the trio, there's a better alternative to asyncio - called Structured Concurrency - and they use different method when spawning a concurrent task - you might stumble on it one day.

For asyncio:

import asyncio


async def task(num: int):
    print(f"task {num} started.")

    # async function need something 'awaitable' to be asynchronous
    await asyncio.sleep(3)

    print(f"task {num} finished.")


async def spawn_task():
    task_list = []

    for n in range(5):
        task_list.append(asyncio.create_task(task(n)))

    await asyncio.gather(*task_list)


asyncio.run(spawn_task())

For threading:

import threading
import time


def thread_workload(num: int):
    print(f"task {num} started.")

    # most of python's IO functions (including time.sleep) release GIL,
    # allowing other thread to run.
    # GIL prevents more than 1 thread running the python code.
    time.sleep(3)

    print(f"task {num} finished.")


def spawn_thread():
    for n in range(5):
        t = threading.Thread(target=thread_workload, args=(n,))
        t.start()


spawn_thread()

For Trio:

import trio


async def task(num: int):
    print(f"task {num} started.")

    # async function need something 'awaitable' to be asynchronous
    await trio.sleep(3)

    print(f"task {num} finished.")


async def spawn_task():
    async with trio.open_nursery() as nursery:
        # explicit task spawning area. Nursery for tasks!

        for n in range(5):
            nursery.start_soon(task, n)


trio.run(spawn_task)

Output:

task 0 started.
task 1 started.
task 2 started.
task 3 started.
task 4 started.
task 0 finished.
task 1 finished.
task 2 finished.
task 3 finished.
task 4 finished.

Upvotes: 3

Related Questions