0

I am new to asynchronous programming.

My understanding is that it is useful for tasks that run in parallel but have a lot of waiting involved. For example, downloading 10 zip archives and decompressing them can be done in parallel but since the "downloading" part is just waiting time for the CPU, asyncio is a useful concept here. Please correct me if I'm wrong.

All tutorials I have seen follow a similar examplary problem as described above and solve it by creating a bunch of awaitables and then await all of them together. (e.g. by gather)

However, it seems a common requirement to me to start such an async operation, e.g. the download of a file, continue to do other work in parallel until the file is actually needed and then retrieve it. This is basically what "futures" represent.

I don't see how this could be implemented with async functions though. If I wouldn't "await" the call to download_file, then it would not even perform the initial setup and the download would not be started. If I would "await" the call immediately, it would wait for the entire download to finish and I wouldn't be able to do any work in parallel. The only solution I came up with is to have download_file return an awaitable future. Is that truly the best way? If so, what even is the point of async, if we still have to use objects like futures like we had to before "async" keywords were introduced?

2
  • I think multithreading may be what you're looking for. Commented Aug 25, 2020 at 21:02
  • 1
    Try a test with asyncio and print something unique, like 'start filename', at the top of the task/coroutine and then something like 'stop filename' and the bottom of the coroutine, see if the event loop switches to the different tasks while waiting for completion. something like the toy examples in this Q&A - Asyncio execution flow issue. Commented Aug 25, 2020 at 21:08

1 Answer 1

1

The solution (in asyncio) is to use something like:

download_task = asyncio.create_task(download_file(...))
... code continues executing ...

This spawns download_file() in the "background" (scare quotes because asyncio is single-threaded, so nothing is truly in the background). You can go about your business then, typically doing other things and, most importantly, awaiting other things, and when you need the download to be completed, use await download_task to get the result.

The only solution I came up with is to have download_file return an awaitable future.

asyncio.create_task() effectively converts any coroutine (async def) into an awaitable future.

If so, what even is the point of async, if we still have to use objects like futures like we had to before "async" keywords were introduced?

The point is that you have coroutines: an extra-convenient tool to implement and compose those futures. You can write a function such as downlooad_file code as if it were ordinary sequential code, and yet have it run in parallel with a bunch of other async code.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.