Reputation: 59
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
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
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