Narrator: To create a useful rain alert application.
We want our script
to detect if it will rain within the next 12 hours
of the Python script being run.
Let's say every day you leave your home at 8:00 AM
in order to go to work,
then by 5:00 or 6:00 PM you might be done with work
and on your way back home.
Given that the free OpenWeatherMap API
gives us the weather forecast in three hour intervals,
we can run the script at 6:00 AM
and check the weather for the next 12 hours.
If there's rain forecast
during the time you're away from home,
you want your Python script to send you a text message,
reminding you to bring an umbrella.
That way you'll get notified before you leave home
and know how to prepare for the day.
In the previous lesson, we saw that the data
that we got back from OpenWeatherMap
contains the weather forecast every three hours
for the next five days.
There are forecasts for 40 different timestamps,
starting from zero and going up all the way to 39.
Now, I dunno about you, but my decision
whether or not to bring an umbrella
really only depends on the forecast
for the next 12 hours.
In the JSON that we got back from OpenWeatherMap,
that would be only the first four forecasts in the list.
If the script is run at 6:00 AM
then a 12-hour window takes us up to 6:00 PM
by which time, we're hopefully ready to head home
and we don't need to worry
if it starts raining much later than that.
If we look at this JSON that we got back,
we don't actually care about the forecasts
that are for tomorrow or those even further in the future.
We just care about the weather
within the next four forecasts.
Looking at the API documentation more closely,
we can actually spot parameters
that will help us to tailor OpenWeatherMaps response,
so that we just get back the data
that we actually care about.
Of course, I'm talking about the cnt or count parameter.
By setting the count to four,
we'll request only four timestamps
covering the 12-hour window that matters to us.
That way we make our own lives easier
and we avoid requesting more data than we actually need.
That's why it's always a good idea to have a read
through the API documentation first.
There are usually some useful nuggets in there
that will make your life as a developer much, much easier.
As I always say, this is like going
into somebody else's house.
Everything is different.
The way that the washing machine works is different.
The way that their dryer works is different.
So you really have
to look at the API documentation when you are working
with a new API, just so that you're not caught out
and you understand exactly what you have to do
in order to be a good API user.
Now, let's go back into our Python code
and provide that extra parameter.
The parameter was called count,
and I'll just add it to our weather_params dictionary.
Let's set count to four,
so that we request only the timestamps in the near future.
Let's run it again and take a look at the JSON response
we get back.
I'm going to copy it again,
go back to the online JSON viewer,
clear that huge amount of data from before
and paste in what I just got back.
You can already see it's much shorter
and if I click on Viewer, we can see that our list
of weather forecasts now only contain
the next four timestamps.
So that's the goal.
And if we head back into our code,
we know that at the moment the response code
that we're getting back from calling this API is 200.
So it's successful.
But we wanna make sure
that we actually catch other response codes.
So we're going to call raise_for_status,
so that if there is a problem
and we don't get a 200 code,
then we actually raise an exception.
Now, next, we wanna save our response.json
as the weather_data
and then we're gonna work with this data
in order to get the particular pieces
that we're interested in.
That's step one done.
The next step is to dig through this hourly forecast
and get hold of the thing that we're interested in,
which is the actual weather condition.
The way that weather services tend
to provide the weather condition is through an id.
And I know this because I read the API documentation.
It's not because I'm some sort of weather geek. (laughs)
Although, I mean that's not a bad thing to be I guess.
If we scroll down in this documentation past the examples,
you can see it provides all of the fields
in the API response.
So these are all of the things
that we could possibly get back and what they mean.
And you can see there's some really interesting things,
like what does the temperature feel like based
on the wind chill and actual ground temperature.
But what we're mostly interested in is the weather data.
So this weather id is a weather condition id,
and when you click on that link, it takes you to this table
that shows you all of the weather condition codes
that we could possibly get back in this particular field.
Now, you can see that all the codes
that start off with 2 means some sort of thunderstorm.
And then starting with 3,
that means some sort of drizzling.
Starting with 5 means rain.
Starting with 6 means snow.
And then afterwards we have the seven hundreds.
So these are atmospheric things like a bit of mist,
a bit of smoke, a bit of dust or fog.
And this is also incidentally the reason why
this weather key actually has a value
that's in the form of a list.
You can see that's denoted by the square brackets here.
So there could actually be multiple weather conditions
for a particular place at a particular hour
and that's because you could maybe have snow,
but you could also have fog at the same time.
Now, when I looked through a lot of the examples
and the documentation, it seems like the first item
in that list is the main condition.
So if it's gonna rain,
then it's gonna be in that first item
in the list of weather conditions.
Inside that list, we have a dictionary or many dictionaries.
Each of those contain a weather condition id,
the main condition name and the description.
So if we look at this id code 802,
we can decode it in this table
and you can see it means scattered clouds.
20 to 50% of the sky is covered in clouds, basically.
Based on this list, we can say that,
well, anything that has a code less than 700,
then we probably will need an umbrella.
I'm not sure how you stand on the umbrella
in snow situation, but I personally do like
to hold an umbrella when it's snowing,
especially because I live in a country
where the snow is not crazy, it's just sort of...
It's never sort of the beautiful snow
where it's thick and it gets caught on your eyelashes.
It's the sort of annoying slush that's just sort of snow,
but it's sort of like somebody spitting at you.
In my case, I would prefer
to have an umbrella if it was gonna snow.
I'm going to check for the codes
that we get back from the OpenWeatherMap API,
and if the code is less than 700,
then I'm gonna advise my user to bring an umbrella.
Here's a challenge for you.
Can you figure out how to look
through the data that we get back,
which remember looks something like this,
and then look at the weather
and the first item in the weather list and also the id?
So you're going to go all the way down to this,
but remember you're gonna do that for all of the items
and you're going to check for the condition code.
Now if any of those id codes are less than 700,
then you want to be able to print out, bring an umbrella.
So that's the goal
and the actual implementation, I'll leave up to you
'cause there's quite a few ways that you can do this,
but I'm sure by now, you are well prepared
with all of your tools in Python to figure this out.
If you wanna make sure that your code is actually working,
you can switch to a latitude and longitude
that is definitely raining.
So if you go to ventusky.com,
they actually show you the live weather forecast.
So we can look at precipitation, which is basically rain,
and we can find some sort of unfortunate place,
which seems to be really heavily raining.
For example, this place in Poland, Lodz,
and if I spell that name correctly.
(keyboard typing)
Lodz and then I'll add the country code Poland
and just to make sure in the map,
it's actually found the correct place.
Yet that looks pretty much it,
then I can switch out my latitude and longitude
with this rainy place
and that way I know that at least one of the results
I get back is definitely going
to contain some sort of rain.
Now if we look at their hourly data,
you can see that the weather
is basically just rain, rain, rain.
So between looking at places which are sunny
and places which are rainy, you should be able
to get your code to work,
so that it tells you in the next 12 hours,
if any of those condition codes are less than 700,
which means it's got some form of precipitation.
Pause the video and give this a go.
All right, so let's narrow down into this weather.
If we want to get the weather,
then we have to tap into the first item in our list
and then we get hold of the weather
and then we get hold of the first item
in that list under the id key, we'll get the actual value.
We've talked about this in detail in previous lessons.
If you've skipped a lot of lessons
and you've come here directly,
then it's gonna be a little bit confusing
and I recommend to review the previous lessons
before you continue.
Instead of printing the weather data, let's drill down.
Let's get to the first item here.
If we provide a set of square brackets
and then we can access the value
inside the list key, like this.
And now, we've got a list with all of the hourly data
and it looks pretty much like this.
Now, you can confirm this
by also pasting this into the JSON viewer,
replacing the previous text that was there.
You can see we now have our items in this list.
To drill further down,
let's get hold of the first item in that list
by providing a square bracket
and then the index, which is zero.
Now, we are into the first item
and this is what the data looks like.
It's a lot shorter.
Now, we wanna tap into the weather condition,
so that means yet another set of square brackets
and then the name of the key, which is weather.
Now, it's pretty simple.
It's simply giving us a list with only one item.
Let's tap into that one item by using again,
square brackets, zero.
And now, we've got just a simple dictionary, essentially.
So if we wanna get hold of the id,
then it's the final square bracket
and the key, which is id.
Now, what if I created a new list
that contains the condition codes?
We know that we've got a list
of all of the weather conditions for the next 12 hours.
How can we loop through that list to find out the actual id
of the weather condition for each of those hours?
Well, we can create a for loop
that looks at each of the data from the hour.
So for hour_data in weather_data list,
so this is gonna go through the 12 hours.
And then for each, we're going to tap into the hour data
and try to get hold of the item
that is in the weather key.
Like this.
Now, I'm going to print each of these
and you can see, we've now got a list
of all of the weather conditions for each of those hours.
Now, let's narrow down that a little bit further.
Let's get hold of the first item of each of these lists.
And you can see, in fact, there's only one item
in all of these lists.
It's very rare that you have multiple weather conditions
for each hour.
Now that gives us a Python dictionary
for each of those hours
and we can tap into that final value we're interested in
under the key id.
So now, we've looped through the next 12 hours
and got hold of the weather condition id
for each of those hours.
Now, all we need to do is to save this
instead of printing it and we'll call it the condition_code.
(keyboard typing)
And remember previously we said
that if the condition code is less than 700,
then we're going to print, bring an umbrella.
So we can check if condition_code,
which remember at this point is still a string.
So we have to turn that into an integer
in order to be able to compare it against another number.
If that condition_code as an integer is less than 700,
then we're going to print, bring an umbrella.
And you can see that for the next 12 hours,
there's rain at this particular place in Lodz in Poland
that I've put into the latitude and longitude.
Now, if I don't want
to call this print statement many times,
then we can define a variable outside the for loop
called will_rain,
and we can set that to false to begin with.
Now if during the next 12 hours the condition_code
is less than 700,
then we'll switch that to equal true instead.
Now, after the for loop has completed,
then we can check to see
if it will_rain in the next 12 hours.
And if so, it will print, bring an umbrella.
This way we'll only get one print statement being called,
instead of every single time
we land on a condition_code for rain.
So this involved quite a bit of JSON passing
and also understanding how to work with parameters and APIs.
Now, I hope you managed to get this far by yourself,
but if not, be sure to review what I've written
and fix your code as required.
If any of it was confusing,
be sure to review previous lessons before you continue
because we're now building heavily
on your previous knowledge
that you learned through the course.
Now, in the next lesson,
we're gonna be looking at how we can,
instead of printing, bring an umbrella
to send a SMS text message
that notifies you to bring an umbrella instead.
So for all of that and more,
I'll see you on the next lesson.