# π¨ This is not concurrent π¨importanyioasyncdefdo_work(name:str):awaitanyio.sleep(1)print(f"Hello, {name}")asyncdefget_data():awaitdo_work(name="Yury")awaitdo_work(name="Nathaniel")awaitdo_work(name="Alex")asyncdefmain():awaitget_data()anyio.run(main)
Python will see the first await, then it will know that this might take a while.
Now Python could run something else that was already waiting somewhere else.
But we didn't tell Python to run anything else during this same period of time.
So Python will just come back and wait for the first await to finish.
Then Python will see the next line to execute and will do all that again.
So, although we use async and await here, this code is not concurrent, at least not the calls to do_work().
If you have something else running it (for example, a FastAPI app), then it will let Python go and do other things during those awaits (for example, handle other requests). That way the program would take some advantage of async and await.
But the calls to do_work() are not concurrent inside of get_data().
This tells this task group to run that function soon.
It won't run it right away and make Python wait for it. Instead, the task group will first receive all the things you want to run and then call them concurrently: during the same period of time.
That's the cue for Python to go and run anything else that might be pending.
At that point, Python will notice another thing pending to run, the next call to do_work() with the arguments name="Nathaniel". It will run it, notice the await, etc.
At some point it will get back to the first await and see that it's now done, so it will continue with that code, and print a message:
If you run the program in the command line, you will see that it will be silent for around 1 second.
And then it will print about everything at once.
This is because Python was waiting for all those anyio.sleep(1) calls concurrently.
So, Python was waiting 1 second in 3 places. But in each of those, it started waiting at around the same time, so it will only take around 1 second for it to run, instead of 3 seconds:
Now, because of the way Asyncer is designed, you will get typing support for your code.
This means that you will have autocompletion in your editor for the original arguments of the async function to call:
And you will have inline errors in your editor too:
If you use tools like mypy, those tools will also be able to help you detect those possible errors.
This can help you write code more efficiently and with more confidence that it's correct. And it will also make sure that whenever you refactor it, you are not breaking anything somewhere else. π