[Python-Dev] A more flexible task creation

Steve Dower steve.dower at python.org
Thu Jun 14 16:03:12 EDT 2018


On 14Jun2018 1214, Chris Barker via Python-Dev wrote:
> Excuse my ignorance (or maybe it's a vocabulary thing), but I'm trying 
> to understand the problem here.
> 
> But if I have this right:
> 
>     I've been using asyncio a lot lately and have encountered this
>     problem several times. Imagine you want to do a lot of queries
>     against a database, spawning 10000 tasks in parallel will probably
>     cause a lot of them to fail.
> 
> 
> async is not parallel -- all the tasks will be run in the same thread 
> (Unless you explicitly spawn another thread), and only one task is 
> running at once, and the task switching happens when the task 
> specifically releases itself.

If the task isn't actually doing the work, but merely waiting for it to 
finish, then you can end up overloading the thing that *is* doing the 
task (e.g. the network interface, database server, other thread/process, 
file system, etc.).

Single-threaded async is actually all about *waiting* - it provides a 
convenient model to do other tasks while you are waiting for the first 
(as well as a convenient model to indicate what should be done after it 
completes - there are two conveniences here).

If the underlying thing you're doing *can* run in parallel, but becomes 
less efficient the more times you do it (for example, most file system 
operations fall into this category), you will want to limit how many 
tasks you *start*, not just how many you are waiting for. I often use 
semaphores for this when I need it, and it looks like 
asyncio.Semaphore() is sufficient for this:


import asyncio
task_limiter = asyncio.Semaphore(4)

async def my_task():
     await task_limiter.acquire()
     try:
         await do_db_request()
     finally:
         task_limiter.release()


Cheers,
Steve


More information about the Python-Dev mailing list