Using Async Functions Inside of Flask Routes

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone in today's video i'm going to talk a little bit about how async works in the latest version of flask because it is now supported and i'm also going to show you an example so what i've done already is i've built an app that is synchronous and it's synchronous but it uses three api calls and the reason why i want to use this as an example is because i can use an async version that calls all three apis at the same time whereas in the synchronous version i have to call one at a time so the first one gets called it waits the second one gets called and then the third one gets called so in this video i'll show you how to convert this over once i show you the code and i'll talk a little bit about how async and flask works but first i just want to say i do have flask courses available i have my flask for beginners course which basically covers everything you need to know to get up and running with flask so if you're not familiar with all the basics of flask i think this course would be good for you i cover both flask and flash sql alchemy and then build some example apps and then i have the flask extensions course which covers some of the most popular extensions for flask it's more like a reference so if you are worrying about how to use a particular extension for example flask wtf i have videos on that so let's take a look at the code here i'm importing the things that i need so i'm using the library httpx so i can perform the request i'm using it because i can use it both with async and without async so i'll show you that in a moment i'm importing time so i can just show you how long it takes for the entire process to happen and then i'm importing some authentication for the apis and i'm using from this auth file and then i have my standard flask imports i have the flask class render template and requests which i'll be using down here and then in state stock pi i just have a list of tuples with the state code and the actual state name so it appears in my drop down so i instantiate flask app and then here i have a route called sync and it's for git and post requests so what i'm basically doing is i'm creating this errors dictionary that will hold any errors that occur in the validation so for example if the first name is missing like here then i'll display first name as required and i'll do the same thing for last name those are pretty simple validation but for the other fields i'm using the api to validate so for example with the email i have errors email here and what i'm doing is i'm just calling the api so this eva ping util here that i'm using and i'm just checking to see if it has the data and if the data is available if it's not deliverable in this particular case i'll just say invalid email address so the api returns other information but that's not really too important for the purposes of this video i don't want to focus too much on the validation part it's more about the async part with multiple api requests so i'm doing something similar for the address the address is a little more complicated because it has more fields but if any part of the address validation fails then all the fields for the address will return is invalid and then finally i have one for the phone number and it does the same thing so if the phone number is valid it returns nothing here in the errors for the phone number if it is invalid then it adds this message and then i'm timing it to show you how long it takes so i can compare the before and after and then i'm just printing it and then i'm rendering the template so this is the same render statement for both the git and posts case this is because i'm going to be dealing with the error messages if they exist and just to show you the form here i have a macro for the form inputs basically it will add a class depending on if it's valid or not and then it will display the error message and basically the rest of the template is just using that macro with the different fields for the drop down i don't need a macro because it's different from the regular text inputs and i believe that's about it so let me get into using this so first let me show you a demo so if i hit submit here all this information here is fine when i hit submit so it all returns is green but for example if i take out the first name i create an invalid number by just adding on some random digits for the email let's say i use something simple like a at gmail.com which should be invalid and then for this address which happens to be one of the addresses for one of the google offices in the us if i change this to be let's say detroit instead of ann arbor and then the zip code is one two three four five instead of the real zip code then when i submit this i should get a bunch of red uh when it returns so here i see i'm missing the first name the phone number is invalid the email address is invalid and all of the address fields are invalid and if i take a look here it tells me how long it took so this was actually pretty quick 2.8 seconds so remember with the synchronous approach i'm calling one api waiting for the response and then i can call the next request waiting for the response and then finally the third and final request and then wait for the response and all this code that takes place in between the requests it's pretty fast so the time spent with that code is negligible because i'm not really going anywhere i'm not calling anything it's just standard python so really the part that takes a long time are the api requests so what i want to do is i want to speed this up by using async in flask so here i have the beginning of basically the same code but as you can see i don't have the api request yet because i'll be adding that in a moment but first i want to talk a little bit about async and flask so async and flask does not mean that flask is truly an async framework meaning the application server calls everything inside of your framework asynchronously that's not the case if you want a true async framework in python you can use something like fast api for instance but in flask it's not true async instead what they give you the ability to do is to create async functions so here if i just add the async here this now becomes an async function and inside of the code here i can await other async functions or code routines as they're called so what happens here when this runs is inside of this function a little world is created for this function only so it's completely independent of everything else in the framework the rest of your app the rest of the server and inside of this little world inside of your function here you can run async code but as soon as it returns here that role goes away so the async no longer applies so you can use as much async as you want inside of this one function here but it can't do anything outside of it so for example you can't start a task on a separate thread and have the ability to get the results of that thread somewhere else it doesn't work like that it only creates an event loop inside of this one particular function runs all the async stuff in it ends the event loop and then returns the data to the user so it's really important to keep in mind when you're doing this so it's not a true async first framework and you don't want to force flask to be something like that because it's not designed to work that way but you can use async things inside of one particular function one particular route which i'll show you how to do in this video so before i get started i just want to warn you that when it comes to doing something like this you have to think about the purpose of using async when you're writing a web app the idea is you want to prevent the user from waiting too long for anything to happen that they need to know about so for example with validation presumably you want to tell them the things that are invalid if they happen to be invalid which is why this is a good use case so i'm checking three different services to tell me if the data that the user has inserted is valid or not if it's invalid i want to tell the user that it's invalid so this works for async because the three requests that i need to perform can all be done using async methods instead of synchronous methods but if you're doing something like sending an email for example you don't necessarily need to tell the user that you've sent an email to them right you just continue on with whatever you're doing in your app and then the email part can kind of be a separate thing so you don't need async for emails instead what you want to do is you want to use something like a separate thread for sending the email or a separate service like celery to send the email because the user doesn't need feedback on what's happening with the email itself they're going to receive the email of course in their email account but that's separate from your actual web app so just keep that in mind and if you have any questions about this difference just feel free to ask me in the comments down below because i do think it can be a little confusing but the general idea is if the user needs to know something and that something can be determined with acing code then that's when you can use async if they don't need to know if it needs to be done but they don't need to know then you don't necessarily need async in this way so now what i want to do is i want to convert the sync example to async so the most important thing i need to do is i need to call all three of the services the three apis that i have so what i want to do is i'm going to use first let me import from async io import async io and down here what i'm going to do is i'm going to call async io.gather so what async io.gather does is it allows me to await multiple code routines and by using the httpx library each request is going to be a code routine and it basically gathers the results of each individual co-routine in a list of results or a tuple just some kind of iterable of results right so it would allow me to do something like this if i do them in the order that i did them above the first response is going to be from the email service so i'll say email response and then the second will be the address response and the third will be the phone number response so phone response and like i said this is an interval it's a tuple really and it's going to return three things when i put them in here it's going to return the response for the email requests the address requests and the phone requests and of course because this is an async routine i have to await it right so now inside of here i need to put the three calls to the apis but before i can do that i need to use the with statements to get the client for performing async requests with httpx so to do that i use with it's actually async with and then http x dot async client so capital a capital c and i can just say ask clients and then i can indent this so this client will allow me to perform async requests this method here of http x dot post or dot git those are sync requests so that's basically the difference when you're using httpx so inside of here i'm going to perform those three in the same order so first i'll get the email one so here i'll get the email one and i'll just copy and paste it paste it in there and it's going to be a list of three things but this should be client instead of httpx so i'll just change that to client and then it's going to perform the request for me then i'll do the same thing for the next one the address and i'll take that and i'll put it in here so i'll just remove the variable and then i'll change this to clients and then put a comma at the end so i can support one more and then the last one will be for the phone number so i'll take the phone number one here copy it put it down here and i'll change the httpx to client so now i have those three and what happens is when it gets to this line of code it's going to initiate pretty much every single request at the same time technically not at the same time but like one right after the other it's not going to wait for the response of the first one before it calls the second one like it does in the sync example so theoretically when we do this the speed of the three requests will just be the speed of the slowest one to return so for example if the first one takes one second the second one takes two seconds and the third one takes three seconds then it will be a total of six seconds spent giving the data which would be the case in the sync example because it has to wait until each one finishes but in the async example since it doesn't have to wait it's just going to take as long as the slowest one which would be three seconds so it will end up being twice as fast as the original sync example so let me just move the data over so it makes more sense because i didn't pass the data and let me just copy this and i'll put the data up here so this is the data for the address requests and then also let me make sure that i have everything else so for the for the email validation i have request form email that's fine for the address i have the data now and then i have the auth that i'm importing from this other file with my credentials and then for the phone number i have the api key which i'm importing from the credentials as well and then i have the phone number and i just have this default country us just to keep it simple you can use these apis for other countries but i'm using the us only to keep it simple and because the address verification api that i'm using only supports us addresses for their free account they allow you to use international addresses as well but you have to pay for that so just to keep it free so everybody can try this i'm just using us addresses only and if you don't live in the us and you don't have an address you can just do what i'm doing and go to some site that has addresses like this one for google and you can try these out in the example so i have those three things there and like i said it should take as long as the slowest one instead of the combined total of all three right and here these will be the actual responses so this code will just wait until all of this is complete so once the slowest one is done then it will move on to the next line so i can exit out of this block and i can start doing the checks that i did before so for example with the email one i can just copy this and paste it after the block with the checks right so this email response is going to come from this block here of the three calls and then it's going to insert the errors and then if i look at the address one here is the address one so i'll just put that one under the email address and then finally i'll do the exact same thing for the phone number so let me just copy the phone number one down and i will put it underneath the address verification and then the rest should be exactly the same because i'm just passing the errors dictionary to the form i'm passing the form data to the form as well just so i can leave it there and then i'm passing the states there so i can run the drop down so let's let's take a look at how long this takes when i run it so let me go back over and here i'm sync and i'm going to move over to async what i'll do is i'll actually open up a new tab and the first thing we see is i need to install flask with the async extras so if you just do pip and saw flask it's only going to install the sync stuff or the typical flask stuff if you want to use async and flask you have to use the extras so to do that i'll just turn off my server and then do pip install flask with the square brackets for async i'll install that so it should be okay now and i'll do flask run again and then i'll go to my form and now we see the form so first let me try putting in some valid information so i'll just copy the atlanta address actually let's keep it exactly the same as the original which is all red so i guess i can pick any example so let's choose austin here so the city is going to be austin and then here's the address so 500 west 2nd street suite 2900 and then the zip code is 78701 the state is texas and then the phone number is going to be this and i'll just remove the extra characters just to keep it simple for email i'll use pretty printed gmail.com which i don't actually use and then for name i'll just do john doe again so let's see if this works when i hit submit so we see the address returns is invalid which is kind of surprising but everything else works so let's take a look at how long this took first this took 1.05 seconds which is basically three times faster than the original so if i go over to my sync example and i use the same information right so i have this address or that phone number this email address will be the same so pretty print it at and then the address will be 500 west 2nd street a suite 2900 austin texas and then the zip code will be 78701 so i'll hit submit on this one and we see it returns valid for the name phone number and email just like the one before but the address for some reason is invalid but we see here this one takes 3.09 seconds right so 3.09 versus 1.072 so i'm guessing in this case each api request takes about one second so in the sync example one second has to pass and then it moves on to the next one and then another second passes and then the final one one second so a total of three seconds whereas in this one like i said they can all get initiated at the same time and then as the results come back they will be processed so it takes as long as the slowest one which is just one second so it's three times faster in this case with pretty much the same exact code so let me use a different address i don't want to investigate too much on why this particular address for the google headquarters doesn't work so i'll just try this one in colorado and says so 2600 pearl streets there's no address to the city is going to be bolder and let me remove that address too and then the states will be colorado so colorado i'll hit submit and now we see it returns green and if i go back it's 1.2 seconds so a little bit slower but it's still pretty fast and if i just put the same information in here so folder and then the address here is 80302 it submits it's going to take a little bit longer and we see it takes 3.1 seconds so in this particular case the async example is much faster the user doesn't have to wait as long to get the same information so that's basically the example that i want to show you so like i said before the reason why you want to use this async stuff is when you want to give the user some kind of information and it requires something that could be used with async so you can have multiple things that could be gathered for instance and you can save time by doing them all at the same time instead of doing them one after the other so i'll have the code to this example in the description below so you can play around with it if you want you'll just have to sign up to the apis i'll put a link in the code to the apis as well if you want to test them out but if you have any questions about this example or anything i talked about in this video feel free to leave a comment down below and i'll try to answer it so that's it for this video if you like this video please give me a thumbs up and if you haven't subscribed to my channel already please subscribe thank you for watching this video and i will talk to you next time
Info
Channel: Pretty Printed
Views: 6,141
Rating: 4.9428573 out of 5
Keywords: async flask, flask async, async, await functions flask, form validation flask
Id: 0z74b3c63GA
Channel Id: undefined
Length: 20min 44sec (1244 seconds)
Published: Mon May 24 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.