>> Let's talk a little bit about asynchronous operations.
Now this is a really big topic
and there's an awful lot that goes into it.
Now just like before,
we're going to stick with the tack that we've taken up until now,
which is we're not going to get really deep into the concept here.
There's an awful lot that's written on
asynchronous programming and specifically async await,
which is what we're going to be taking a look at.
If you've done say, C Sharp or JavaScript or TypeScript,
I love TypeScript, you've very likely experienced async await.
They're really common in those environments.
Well, JavaScript becoming more so than it was in the past,
and so what we want to do here is take a look
at how this is done in Python.
So I'm going to start off a little bit by talking a bit
about what asynchronous programming is all about.
We'll take a look at asynchronous example,
and then we'll get in and see how we could do that asynchronously,
and the performance improvement
that we're going to wind up getting here.
So the long and short of it is
the fact that the waiting is the hardest part.
That certain operations just take a little bit of time.
Maybe I'm making a web call, I've got network IO,
I'm doing some fancy processing, whatever it is.
We don't want to stop everything just because one operation
is taking its own sweet time to do whatever it is that it's doing.
Now this basic concept of being
able to execute some bit of code or being able to
mark our process as sleepable while
something else happens maybe outside of our app or otherwise,
all of that falls under
this very large umbrella of concurrency and parallelism.
Again, this is a really broad topic.
We're not going to get real deep into it at all.
This is basically the main slide that we have on this,
and what I want to highlight is the fact
that really any programming language,
any framework, is going to have some level of options that
you'll be able to take advantage of when it
comes to concurrency and parallelism.
Python is no exception.
That we have a lot of
different ways that we could actually spin up threads,
that we can go ahead and do locking to make
sure that values aren't changing unexpectedly,
or that if we go in and change a value,
that we're not going to mess somebody else up,
something else up, etc.
What we're going to do with our demo is we're going to
focus in on probably the most common scenario,
which is a web request.
Because just HTTP or HTTPS,
it's a heavy protocol.
So just having to wait for that request to go up, to come back,
just the buildup and the tear-down of
that connection in and of itself takes a little while.
So it'd be nice if we could go ahead and mark
our application as the fact that it's going to be
running this or maybe be able to just do something else
while that long running operation is taking place.
In Python, starting with Python 3.4,
we got this asyncio module.
What this is going to do is it's going to graft or
bring asynchronous development into Python.
Asyncio is going to give us
all the usual suspects when it comes
to doing some form of asynchronous programming.
It's going to give us asynchronous streams,
it's going to give us the ability to do
synchronization or locking, unlocking.
It's going to help us out an awful lot with exception management,
that one of the things that can get really tricky really
quickly is if I'm creating
another thread and that thread throws an exception,
how am I if I'm sitting over here know what's happened over there?
So making sure that our exceptions bubble out appropriately.
All of that is really important and
the asyncio module is going to take care of that for us.
The big thing that it's going to do is it's going
to give to us async await.
Let's talk a little bit about async await.
So here's a big block of code here,
and what I want to focus in on is
a couple of really important keywords here.
The first is going to be await.
What await is going to do is it's
going to logically pause our code.
That the next line of code here,
this little line of code,
let's just go ahead and number that as,
let's just say the number three here.
There we go. So our third line of code there,
that's not going to execute
until the operation up above completes.
So if we stop and we look at this,
this looks very synchronous because
that's normally the way that our code works.
That normally what happens,
we have line of code gives us a value,
line of code gives us a value,
line of code gives us a value.
We're all used to that.
That's normally the way that our code behaves.
What's happening here though is different.
It looks a little subtle,
but it's different in a very big way.
That while yes, by my putting in that await,
I'm blocking execution here.
Something else kind of magical is also happening.
I'm now telling my code,
hey, we're now going to be waiting on something.
So A, the runtime is going to be
able to go off and potentially do something else.
So that way if it needs access to the process,
it can do that.
But also, B, is I can start a long running process,
start another long running process,
maybe start a third long-running process,
and then go, okay,
now I need that first value back.
That's exactly what's going on up above right here.
So what I want you to notice right here is I'm creating
two items here called two task, and three tasks.
I'm creating what are known as tasks.
In fact, you can see right here off
of asyncio that I'm calling exactly that.
I'm calling a task.
Well, what's a task?
A task is really like a promise, it's an IOU.
It's basically me setting up a method.
That method is going to execute and when it finishes,
it's going to get back to me.
So basically what I'm doing here is I'm saying, hey,
go do this thing,
and when you're done doing this thing, let me know.
So promise me that you'll let me know and it goes yep,
I promise I'll go ahead and let you know.
Then it starts going off and doing its execution.
So what is it actually doing?
Well for us, it's calling this little function
that we'll analyze in just a second here, called load data.
Now as the name implies,
it's going to load data.
Loading data sometimes takes a little while.
So it's going to go off and it's going to load up our data.
It's going to execute some long running operation.
We're going to set this up as a task.
So now both of those you're going to be running off to the side.
They're going to be doing their own thing.
Then I can keep executing code.
You'll notice that right here I've got my
little doing work because that's exactly what's happening,
is I create those tasks,
I know there are running.
I trust them. They made me a promise.
We're all good there, we're all buddy-buddy.
So I know those are doing those things so I
can now focus in on other things.
So I don't have to stop
just because I know that's going to take a little bit.
Then once I'm finally ready to go get the answer.
So I told them, hey, go load some data.
Now I'm actually ready to get that data.
So now I can go ahead and grab that data by using that await.
So now what that's going to do is say, all right,
stop here, wait until we get a response back.
Then we're going to put that in two, in our case,
this little two results and this little three results.
Now the other thing that you're going to notice here is the fact
that we're doing a little bit of timing.
You're going to notice that down at the very bottom,
we've already got the output there that it's going to tell us
that the operation took 3.4 seconds.
Okay, well, why is that significant?
Well, the reason that that's significant
is load data is going to be
calling an endpoint that just pauses for X number of seconds.
X in our case is going to be 2 and 3.
So that first one is going to be 2 that second one is 3.
So if this would have occurred synchronously,
this would have taken a total of five seconds.
Two plus 3 equals 5.
In our case, it took 3.4.
The reason that it took 3.4, well,
you're going to notice right here
that we've got our three second delay here.
So it's taking at least three seconds.
It's taking a little bit more than that because, again, HTTP,
heavy protocol takes a little buildup a request
little bit to tear that down.
Last little thing that I want to highlight on this screen,
and then I wanted to take a look at load data,
is this little [inaudible] right here,
this little async thing right here.
You're going to notice that there's one right up above.
So what is an async doing?
Well, async is saying, hey,
in this construct we're going to call await.
What that also in turn means is
the fact that somebody else is going to call
this function can also
await on whatever the operation is inside of here.
If you're going to use await,
it always has to be inside of an async construct.
So you'll notice in this case here that
it's inside of that little function.
If we take this one step further,
if we go take a look at that load data,
now what you're going to notice is
that load data was flagged as async.
Again, what that now means is that
I can say something like result equals
awaits load data and then my session variable,
and then whatever the delay happens to be there.
So now again, my code is going to pause here.
I'm saying, hey, this is going to be a long running operation.
So now my process is free to do
other things until we get the value back.
But again, logically, my code is going to pause right here.
It's not going to go beyond that until that returns back a value.
So this little async await is going to give us that ability.
It gives us a very clean way to
go in and set up asynchronous programming.
Now you're also going to notice in this code here that there's
a couple of other libraries that we're pulling in.
We're calling out to some external endpoint and so forth.
I want to tie all of that together.
But I think the best way to tie all of that
together is to actually go take a look at the code.
So we've seen the slides,
we've explained the concept.
So async means that I can await on that function,
and I can also put awaits inside of there.
Await means, hey, we're going to logically pause code here,
wait for a response to actually come back.
But our process is still free to do other things if it so desires.
It gives us again that nice clean way
to go ahead and set up asynchronous programming.
Again, I think we go in,
take a look at a code,
take a look at asynchronous comparison
here that will hopefully help bring it all together.
So let's go do that.