K K
K K

Reputation: 33

make a dict result by python coroutines just like node.js async.parallel

I want to make a dict in python, like the following node.js codes:

async = require('async');
async.parallel({
    html: (done) => {
        //get html from url
        html = 'html codes...'
        done(null, html)
    },

    data: (done) => {
        //get data from db
        data = [
            {
                id: 1,
                name: 'Jay',
            },
            {
                id: 2,
                name: 'Jonh',
            }
        ]
        done(null, data)
    },
}, (err, result) => {
    console.log('html', result.html)
    console.log('data', result.data)
});

The above execute two parallel tasks, and return the result contains the key with 'html' and 'data' to flag.

I want to do same thing in pytnon, but I don't know how to make it by asyncio, see the following codes:

import asyncio

async def get_html():
    await asyncio.sleep(1)
    html = 'html codes...'
    return html

async def get_data():
    await asyncio.sleep(1)
    data = [
        {
            'id': 1,
            'name': 'Jay',
        },
        {
            'id': 2,
            'name': 'Jonh',
        }
    ]
    return data

async def main():
    tasks = [get_html(), get_data()]
    result = await asyncio.gather(*tasks)
    print(type(result)) # But it's a list
    # result['html']   #I want it is contains key with 'html' and 'data'
    # result['data']
    print(result[0]) # I dont know which is html
    print(result[1]) # And which is data


loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

Thanks in advance! :)

Upvotes: 1

Views: 839

Answers (1)

Aleph Aleph
Aleph Aleph

Reputation: 5395

First, you should use await with asyncio.sleep().

You can use the following function - credits to the author of this gist:

import asyncio
from typing import Awaitable, Dict, Tuple

async def gather_dict(tasks: Dict[str, Awaitable[str]]) -> Dict[str, str]:
    async def mark(key: str, coro: Awaitable[str]) -> Tuple[str, str]:
        return key, await coro

    return {
        key: result
        for key, result in await asyncio.gather(
            *(mark(key, coro) for key, coro in tasks.items())
        )
    }

async def main():
    result = await gather_dict({'html': get_html(), 'data': get_data()})
    print(result)

This will execute the two coroutines in parallel and print: {'html': 'html codes...', 'data': [{'id': 1, 'name': 'Jay'}, {'id': 2, 'name': 'Jonh'}]}

Upvotes: 3

Related Questions