аватар question@mail.ru · 01.01.1970 03:00

Python when should I use ASYNC, and when is AWAIT?

when should I use ASYNC, and when AWAIT?

аватар answer@mail.ru · 01.01.1970 03:00

I will try to supplement @ext's answer.

async/await is an optimization, i.e. it is absolutely not necessary to use them where everything is already working well. After all, this complicates the logic of program execution and entails a lot of things. Because if you decide to use asynchronous functionality, please use ONLY libraries that support it.

Asynchronous code execution is similar to multithreaded code execution on a single-core processor. There are also several tasks that can be performed simultaneously, and there is a context for each task. However, with multithreading, the processor itself decides on a timer when to switch the context and perform another task.

The asynchronous approach assumes that the application itself defines special places where such switching is possible. In Python, in asyncio, these places become calls with await.

If you decide to optimize, then first of all it is worth remembering what CPU-bound and IO-bound operations are and how they differ. The former are constantly using processor resources, counting and calculating things all the time. The latter spend most of their time waiting for input/output operations from the file system, network, or who knows what else.

Due to the GIL in Python (CPython), CPU-bound operations cannot be optimized using threads, only by taking them out into a separate process. Exactly the same restriction is imposed on using an asynchronous approach, because asynchronous code is predominantly single-core, and if one executor switches from one process to another where his presence is equally important, there will be no benefit (it will be much worse).

IO-bound tasks are another matter. Vivid examples include - reading files, querying the database, even time.sleep (which is often used to simulate complex IO-bound operations and there is a special asyncio.sleep).

For example:

def/span> create_report_report(cursor, *args, **kwargs): # perform some preparatory work data = cursor.execute(sql_query) # process the received data and generate a report

Here, the execute function will not load the processor too much, it will wait more for a response from the database.e from the database. Therefore, the processor is allowed to do something else at this moment. But this code is synchronous, so you have to wait. If we need to build a lot of such reports, then we can decide to optimize it using asyncio. Let's try it.

First, we will have to throw out the old client to go to the database and use a special asynchronous one that will make a non-blocking call.

async/span> def"">def create>create_report(cursor, *args, **kwargs):    # cursor - this is not the cursor from the previous example # do some preparatory work data =pan> data  await cursor.execute(sql_query) # process the received data and generate a report

Any function that uses await must be declared as async - there is no choice. And await announces a point in the program at which we can switch to other useful work, if there is one, because processor resources are not needed here. This way we can do more.

I leave out the initialization of the event-loop and other delights of running asynchronous programs.

It's very important to say "A" (async), say "B" (await), they don't exist without each other.

I found the following information extremely clear:

I don't know if there is a translation of this stuff on the Inteet, but if you need it, I could prepare it.

Finally, an interesting statement: ""use asynchrony when you can, and threads when you have to"".

Latest

Similar