ikrma ahmad
ikrma ahmad

Reputation: 59

how do python handle asynchronous task

I've strong background in a JS frameworks. Javascript is single threaded language and during the execution of code when it encounters any async task, the event loop plays the important role there.

Now I've been into Python/Django and things are going good but I'm very curious about how python handle any asynchronous tasks whenever I need to make a database query in django, I simple use the queryset method like

def func(id):
    do_somthing()
    user = User.objects.get(id=id)
    do_somthing_with_user()


func()
another_func()

I've used the queryset method that fetch something from database and is a asynchronous function without await keyword. what will be the behaviour of python there, is it like block the execution below until the queryset response, is it continue the execution for the rest of code on another thread.

Also whenever we need to make an external request from python, we uses requests library method without await keyword,

r = request.get("https://api.jsonplaceholder.com/users")
# will the below code executes when the response of the request arrive?
do_somthing()
.
.
.
do_another_thing()

does python block the execution of code until the response arrives?

In JS the async task is handled by event loop while the rest of the code executes normally

console.log("first")

fetch("https://api.jsonplaceholder.com/users").then(() => console.log("third"))

console.log("second")

the logs in console will be

first second third

How Python Handles these type things under the hood?

Upvotes: 0

Views: 195

Answers (2)

Ajithkumar M
Ajithkumar M

Reputation: 39

asynchronous programming allows you to execute tasks concurrently without blocking the main execution.

import asyncio

async def func(id):
    do_something()
    loop = asyncio.get_event_loop()
    user = await loop.run_in_executor(None, User.objects.get, id)
    do_something_with_user()

async def main():
    await func(id)
    await another_func()

asyncio.run(main())

Upvotes: 0

Gracen Ownby
Gracen Ownby

Reputation: 474

The await command needs to be used specifically when you are running an asynchronous function that calls synchronous functions. This synchronous function is ran as a coroutine and has an object name coroutine when debugging. To run a coroutine, it must be scheduled on the event loop. Using the await keyword releases control back to the event loop. Instead of awaiting a coroutine, you can also setup a task to schedule a coroutine to run at a certain time using the asyncio package. See documentation

asyncio.create_task(coro, *, name=None, context=None)

Python does not block execution but rather ensures that it happens at the correct time using CPU parallelism. Using a method like request.get() should not create any forthcoming errors because you are accessing values over the internet and not locally. Network requests move, essentially at the speed of light, where as database requests on the server are limited by the speed of the SSD or HDD. This was more of an issue on old drives where you are literally waiting for a disk to spin, but the idea of properly managing these local resources is still a issue that has to be solved in order for the asynchronous application to work. When making calls to the sql database, make sure to use the decorator @database_sync_to_async above the regular 'synchronous' functions that your asynchronous function calls.

from channels.db import database_sync_to_async

For more information check out the django documentation on asynchronous support.

Upvotes: 0

Related Questions