Difference between coroutine and future/task in Python 3.5?

Let's say we have a dummy function:

    async def foo(arg):
        result = await some_remote_call(arg)
        return result.upper()

What's the difference between:

    coros = []
    for i in range(5):

    loop = get_event_loop()


    from asyncio import ensure_future

    futures = []
    for i in range(5):

    loop = get_event_loop()

Note : The example returns a result, but this isn't the focus of the question. When return value matters, use gather() instead of wait().

Regardless of return value, I'm looking for clarity on ensure_future(). wait(coros) and wait(futures) both run the coroutines, so when and why should a coroutine be wrapped in ensure_future?

Basically, what's the Right Way (tm) to run a bunch of non-blocking operations using Python 3.5's async?

For extra credit, what if I want to batch the calls? For example, I need to call some_remote_call(...) 1000 times, but I don't want to crush the web server/database/etc with 1000 simultaneous connections. This is doable with a thread or process pool, but is there a way to do this with asyncio?

A comment by Vincent linked to https://github.com/python/asyncio/blob/master/asyncio/tasks.py#L346, which shows that wait() wraps the coroutines in ensure_future() for you!

In other words, we do need a future, and coroutines will be silently transformed into them.

I'll update this answer when I find a definitive explanation of how to batch coroutines/futures.

From: stackoverflow.com/q/34753401