简体   繁体   中英

How to implement async method in python

I want to implement async method in the following code:

import time

def main(num):
    num_list = []
    for i in range(num):
        num_list.append(i)
        print("The number that is added in list is:", i)
        time.sleep(2)
    return num_list


def count():
    start_time = time.time()
    num_list = [3,5,2,8,2]
    for i in num_list:
        print("\nIn count() = ", i)
        data = main(i)
        print("Got data from main() = ", data)
        time.sleep(2)
    total_time = time.time() - start_time
    print("The code took",total_time,"seconds to complete")

if __name__ == "__main__":
    count()

This code takes 50s to complete. I tried to implement async method in this code but I was not able to succeed because I just started learning about it. Can you tell me how can I implement async method in this code.

Here's the code where I tried to implement async method:

import asyncio, time
from asgiref.sync import sync_to_async

@sync_to_async
def main(num):
    num_list = []
    for i in range(num):
        num_list.append(i)
        print("The number that is added in list is:", i)
        time.sleep(2)
    return num_list

def get_data(data_var):
    try:
        data_var.send(None)
    except StopIteration as e:
        return e.value


async def count():
    start_time = time.time()
    num_list = [3,5,2,8,2]
    for i in num_list:
        print("In count() :".format(i))
        task1 = asyncio.ensure_future(main(i))
        data = get_data(main(i))
        print("In main() = {}".format(data))
        await asyncio.sleep(2)
        await task1
    total_time = time.time() - start_time
    print("The code took",total_time, "seconds to complete")

if __name__ == "__main__":
    asyncio.run(count())

And I am not getting num_list as return value instead I am getting None.

If you can convert your main into async function, then it can be written as this.

import asyncio
import time
from loguru import logger


async def main(num):
    num_list = []
    for i in range(num):
        num_list.append(i)
        logger.info(f"The number that is added in list is: {i}")
        await asyncio.sleep(2)
    return num_list


async def count():
    start_time = time.time()
    num_list = [3,5,2,8,2]
    task_list = []
    for i in num_list:
        logger.info(f"In count() = {i}")
        task = asyncio.create_task(main(i))
        task_list.append(task)
    result_list = await asyncio.gather(*task_list)
    for r in result_list:
        logger.info(f"Got data from main() = {r}")
    total_time = time.time() - start_time
    logger.info(f"The code took {total_time} seconds to complete")

loop = asyncio.get_event_loop()
loop.run_until_complete(count())

If you can't convert the main function, threading is your best bet.

from concurrent.futures import ThreadPoolExecutor, as_completed
from loguru import logger

def main(num):
    num_list = []
    for i in range(num):
        num_list.append(i)
        logger.info(f"The number that is added in list is: {i}")
        time.sleep(2)
    return num_list


def count():
    start_time = time.time()
    num_list = [3,5,2,8,2]
    with ThreadPoolExecutor(max_workers=5) as executor:
        futures = {}
        for k in num_list:
            logger.info(f"In count() = {k}")
            futures[executor.submit(main, k)] = k
        for future in as_completed(futures):
            logger.info(f"Got data from main() = {future.result()}")
            time.sleep(2)
        total_time = time.time() - start_time
        logger.info(f"The code took {total_time} seconds to complete")

count()

Both will achieve the same goal in terms of overall execution time.

That is really not the way to do asynchronous programming, check out this article

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM