WEBVTT

0
00:00.720 --> 00:03.630
To create a useful rain alert application.

1
00:03.630 --> 00:04.920
We want our script

2
00:04.920 --> 00:08.640
to detect if it will rain within the next 12 hours

3
00:08.640 --> 00:11.130
of the Python script being run.

4
00:11.130 --> 00:13.680
Let's say every day you leave your home at 8:00 AM

5
00:13.680 --> 00:15.150
in order to go to work,

6
00:15.150 --> 00:18.990
then by 5:00 or 6:00 PM you might be done with work

7
00:18.990 --> 00:21.240
and on your way back home.

8
00:21.240 --> 00:24.000
Given that the free OpenWeatherMap API

9
00:24.000 --> 00:27.990
gives us the weather forecast in three hour intervals,

10
00:27.990 --> 00:30.120
we can run the script at 6:00 AM

11
00:30.120 --> 00:33.240
and check the weather for the next 12 hours.

12
00:33.240 --> 00:34.560
If there's rain forecast

13
00:34.560 --> 00:36.690
during the time you're away from home,

14
00:36.690 --> 00:39.630
you want your Python script to send you a text message,

15
00:39.630 --> 00:42.060
reminding you to bring an umbrella.

16
00:42.060 --> 00:45.270
That way you'll get notified before you leave home

17
00:45.270 --> 00:47.133
and know how to prepare for the day.

18
00:48.450 --> 00:50.700
In the previous lesson, we saw that the data

19
00:50.700 --> 00:53.010
that we got back from OpenWeatherMap

20
00:53.010 --> 00:55.830
contains the weather forecast every three hours

21
00:55.830 --> 00:57.720
for the next five days.

22
00:57.720 --> 01:00.960
There are forecasts for 40 different timestamps,

23
01:00.960 --> 01:04.950
starting from zero and going up all the way to 39.

24
01:04.950 --> 01:07.650
Now, I don't know about you, but my decision

25
01:07.650 --> 01:09.420
whether or not to bring an umbrella

26
01:09.420 --> 01:11.640
really only depends on the forecast

27
01:11.640 --> 01:13.530
for the next 12 hours.

28
01:13.530 --> 01:16.410
In the JSON that we got back from OpenWeatherMap,

29
01:16.410 --> 01:20.250
that would be only the first four forecasts in the list.

30
01:20.250 --> 01:22.410
If the script is run at 6:00 AM

31
01:22.410 --> 01:26.520
then a 12-hour window takes us up to 6:00 PM

32
01:26.520 --> 01:29.430
by which time, we're hopefully ready to head home

33
01:29.430 --> 01:30.480
and we don't need to worry

34
01:30.480 --> 01:32.793
if it starts raining much later than that.

35
01:33.690 --> 01:36.180
If we look at this JSON that we got back,

36
01:36.180 --> 01:38.550
we don't actually care about the forecasts

37
01:38.550 --> 01:42.300
that are for tomorrow or those even further in the future.

38
01:42.300 --> 01:43.650
We just care about the weather

39
01:43.650 --> 01:46.290
within the next four forecasts.

40
01:46.290 --> 01:49.260
Looking at the API documentation more closely,

41
01:49.260 --> 01:51.330
we can actually spot parameters

42
01:51.330 --> 01:55.140
that will help us to tailor OpenWeatherMaps response,

43
01:55.140 --> 01:56.850
so that we just get back the data

44
01:56.850 --> 01:58.590
that we actually care about.

45
01:58.590 --> 02:03.590
Of course, I'm talking about the cnt or count parameter.

46
02:03.660 --> 02:06.330
By setting the count to four,

47
02:06.330 --> 02:09.090
we'll request only four timestamps

48
02:09.090 --> 02:12.540
covering the 12-hour window that matters to us.

49
02:12.540 --> 02:14.820
That way we make our own lives easier

50
02:14.820 --> 02:18.240
and we avoid requesting more data than we actually need.

51
02:18.240 --> 02:20.550
That's why it's always a good idea to have a read

52
02:20.550 --> 02:24.000
through the API documentation first.

53
02:24.000 --> 02:25.950
There are usually some useful nuggets in there

54
02:25.950 --> 02:29.700
that will make your life as a developer much, much easier.

55
02:29.700 --> 02:31.530
As I always say, this is like going

56
02:31.530 --> 02:33.120
into somebody else's house,

57
02:33.120 --> 02:34.260
everything is different.

58
02:34.260 --> 02:36.780
The way that the washing machine works is different,

59
02:36.780 --> 02:39.060
the way that their dryer works is different,

60
02:39.060 --> 02:40.440
so you really have

61
02:40.440 --> 02:43.590
to look at the API documentation when you are working

62
02:43.590 --> 02:46.380
with a new API, just so that you're not caught out

63
02:46.380 --> 02:49.170
and you understand exactly what you have to do

64
02:49.170 --> 02:52.053
in order to be a good API user.

65
02:53.370 --> 02:55.890
Now, let's go back into our Python code

66
02:55.890 --> 02:58.350
and provide that extra parameter.

67
02:58.350 --> 03:00.240
The parameter was called count,

68
03:00.240 --> 03:04.110
and I'll just add it to our weather_params dictionary.

69
03:04.110 --> 03:05.730
Let's set cnt to 4,

70
03:05.730 --> 03:09.630
so that we request only the timestamps in the near future.

71
03:09.630 --> 03:14.490
Let's run it again and take a look at the JSON response

72
03:14.490 --> 03:15.810
we get back.

73
03:15.810 --> 03:17.190
I'm going to copy it again,

74
03:17.190 --> 03:19.590
go back to the online JSON viewer,

75
03:19.590 --> 03:22.530
clear that huge amount of data from before

76
03:22.530 --> 03:24.750
and paste in what I just got back.

77
03:24.750 --> 03:26.880
You can already see it's much shorter,

78
03:26.880 --> 03:29.580
and if I click on Viewer, we can see that our list

79
03:29.580 --> 03:31.920
of weather forecasts now only contain

80
03:31.920 --> 03:33.993
the next four timestamps.

81
03:35.070 --> 03:36.480
So that's the goal.

82
03:36.480 --> 03:39.360
And if we head back into our code,

83
03:39.360 --> 03:42.180
we know that at the moment the response code

84
03:42.180 --> 03:45.900
that we're getting back from calling this API is 200.

85
03:45.900 --> 03:47.520
So it's successful.

86
03:47.520 --> 03:48.750
But we want to make sure

87
03:48.750 --> 03:51.900
that we actually catch other response codes.

88
03:51.900 --> 03:54.750
So we're going to call raise_for_status(),

89
03:54.750 --> 03:57.150
so that if there is a problem

90
03:57.150 --> 03:59.220
and we don't get a 200 code,

91
03:59.220 --> 04:01.293
then we actually raise an exception.

92
04:02.400 --> 04:06.450
Now, next, we want to save our response.json()

93
04:06.450 --> 04:07.840
as the weather_data

94
04:09.480 --> 04:11.040
and then we're going to work with this data

95
04:11.040 --> 04:13.380
in order to get the particular pieces

96
04:13.380 --> 04:14.630
that we're interested in.

97
04:15.600 --> 04:17.520
So that's step one done.

98
04:17.520 --> 04:21.900
The next step is to dig through this hourly forecast

99
04:21.900 --> 04:24.750
and get hold of the thing that we're interested in,

100
04:24.750 --> 04:28.170
which is the actual weather condition.

101
04:28.170 --> 04:30.390
The way that weather services tend

102
04:30.390 --> 04:34.290
to provide the weather condition is through an id.

103
04:34.290 --> 04:38.730
And I know this because I read the API documentation.

104
04:38.730 --> 04:42.630
It's not because I'm some sort of weather geek. (laughs)

105
04:42.630 --> 04:45.930
Although, I mean that's not a bad thing to be I guess.

106
04:45.930 --> 04:50.930
So if we scroll down in this documentation past the examples,

107
04:51.000 --> 04:53.010
you can see it provides all of the fields

108
04:53.010 --> 04:54.600
in the API response.

109
04:54.600 --> 04:56.280
So these are all of the things

110
04:56.280 --> 04:59.760
that we could possibly get back and what they mean.

111
04:59.760 --> 05:01.920
And you can see there's some really interesting things,

112
05:01.920 --> 05:05.250
like what does the temperature feel like based

113
05:05.250 --> 05:08.850
on the wind chill and actual ground temperature.

114
05:08.850 --> 05:13.020
But what we're mostly interested in is the weather data.

115
05:13.020 --> 05:18.020
So this weather.id is a weather condition id,

116
05:18.480 --> 05:21.660
and when you click on that link, it takes you to this table

117
05:21.660 --> 05:24.750
that shows you all of the weather condition codes

118
05:24.750 --> 05:29.103
that we could possibly get back in this particular field.

119
05:30.030 --> 05:31.860
Now, you can see that all the codes

120
05:31.860 --> 05:36.860
that start off with 2, means some sort of thunderstorm,

121
05:37.230 --> 05:38.730
and then starting with 3,

122
05:38.730 --> 05:40.380
that means some sort of drizzling,

123
05:40.380 --> 05:42.450
starting with 5 means rain,

124
05:42.450 --> 05:44.550
starting with 6 means snow,

125
05:44.550 --> 05:47.460
and then afterwards we have the seven hundreds.

126
05:47.460 --> 05:50.340
So these are atmospheric things like a bit of mist,

127
05:50.340 --> 05:53.040
a bit of smoke, a bit of dust or fog.

128
05:53.040 --> 05:55.920
And this is also incidentally the reason why

129
05:55.920 --> 06:00.000
this weather key actually has a value

130
06:00.000 --> 06:02.070
that's in the form of a list.

131
06:02.070 --> 06:05.250
You can see that's denoted by the square brackets here.

132
06:05.250 --> 06:08.730
So there could actually be multiple weather conditions

133
06:08.730 --> 06:12.180
for a particular place at a particular hour,

134
06:12.180 --> 06:16.020
and that's because you could maybe have snow,

135
06:16.020 --> 06:18.753
but you could also have fog at the same time.

136
06:19.740 --> 06:22.260
Now, when I looked through a lot of the examples

137
06:22.260 --> 06:26.010
and the documentation, it seems like the first item

138
06:26.010 --> 06:28.710
in that list is the main condition.

139
06:28.710 --> 06:30.030
So if it's going to rain,

140
06:30.030 --> 06:32.160
then it's going to be in that first item

141
06:32.160 --> 06:35.070
in the list of weather conditions.

142
06:35.070 --> 06:39.630
Inside that list, we have a dictionary or many dictionaries.

143
06:39.630 --> 06:42.870
Each of those contain a weather condition id,

144
06:42.870 --> 06:46.260
the main condition name, and the description.

145
06:46.260 --> 06:49.410
So if we look at this id code 802,

146
06:49.410 --> 06:51.780
we can decode it in this table

147
06:51.780 --> 06:54.540
and you can see it means scattered clouds.

148
06:54.540 --> 06:57.903
20-50% of the sky is covered in clouds, basically.

149
06:59.370 --> 07:01.500
Based on this list, we can say that,

150
07:01.500 --> 07:05.550
well, anything that has a code less than 700,

151
07:05.550 --> 07:08.730
then we probably will need an umbrella.

152
07:08.730 --> 07:11.400
I'm not sure how you stand on the umbrella

153
07:11.400 --> 07:15.180
in snow situation, but I personally do like

154
07:15.180 --> 07:17.130
to hold an umbrella when it's snowing,

155
07:17.130 --> 07:18.780
especially because I live in a country

156
07:18.780 --> 07:22.130
where the snow is not crazy, it's just sort of...

157
07:23.220 --> 07:26.670
It's never sort of the beautiful snow

158
07:26.670 --> 07:29.310
where it's thick and it gets caught on your eyelashes.

159
07:29.310 --> 07:33.810
It's the sort of annoying slush that's just sort of snow,

160
07:33.810 --> 07:37.380
but it's sort of like somebody spitting at you.

161
07:37.380 --> 07:38.940
In my case, I would prefer

162
07:38.940 --> 07:41.820
to have an umbrella if it was going to snow.

163
07:41.820 --> 07:44.040
I'm going to check for the codes

164
07:44.040 --> 07:47.010
that we get back from the OpenWeatherMap API,

165
07:47.010 --> 07:49.890
and if the code is less than 700,

166
07:49.890 --> 07:53.553
then I'm going to advise my user to bring an umbrella.

167
07:55.290 --> 07:57.690
Here's a challenge for you.

168
07:57.690 --> 08:00.150
Can you figure out how to look

169
08:00.150 --> 08:01.800
through the data that we get back,

170
08:01.800 --> 08:05.073
which remember looks something like this,

171
08:05.910 --> 08:08.910
and then look at the weather

172
08:08.910 --> 08:13.410
and the first item in the weather list and also the id?

173
08:13.410 --> 08:16.800
So you're going to go all the way down to this,

174
08:16.800 --> 08:19.830
but remember you're going to do that for all of the items

175
08:19.830 --> 08:22.410
and you're going to check for the condition code.

176
08:22.410 --> 08:26.700
Now if any of those id codes are less than 700,

177
08:26.700 --> 08:30.330
then you want to be able to print out, "Bring an umbrella".

178
08:30.330 --> 08:32.340
So that's the goal

179
08:32.340 --> 08:35.460
and the actual implementation, I'll leave up to you

180
08:35.460 --> 08:37.800
'cause there's quite a few ways that you can do this,

181
08:37.800 --> 08:40.710
but I'm sure by now, you are well prepared

182
08:40.710 --> 08:44.400
with all of your tools in Python to figure this out.

183
08:44.400 --> 08:48.180
If you want to make sure that your code is actually working,

184
08:48.180 --> 08:50.730
you can switch to a latitude and longitude

185
08:50.730 --> 08:52.860
that is definitely raining.

186
08:52.860 --> 08:56.130
So if you go to ventusky.com,

187
08:56.130 --> 08:59.340
they actually show you the live weather forecast.

188
08:59.340 --> 09:03.270
So we can look at precipitation, which is basically rain,

189
09:03.270 --> 09:06.000
and we can find some sort of unfortunate place,

190
09:06.000 --> 09:09.060
which seems to be really heavily raining.

191
09:09.060 --> 09:11.313
For example, this place in Poland, Lodz,

192
09:12.270 --> 09:16.145
and if I spell that name correctly.

193
09:16.145 --> 09:19.200
(keyboard typing)

194
09:19.200 --> 09:22.560
Lodz and then I'll add the country code Poland,

195
09:22.560 --> 09:24.750
and just to make sure in the map,

196
09:24.750 --> 09:27.510
it's actually found the correct place.

197
09:27.510 --> 09:29.280
Yet that looks pretty much it,

198
09:29.280 --> 09:32.310
then I can switch out my latitude and longitude

199
09:32.310 --> 09:34.260
with this rainy place,

200
09:34.260 --> 09:37.470
and that way I know that at least one of the results

201
09:37.470 --> 09:39.480
I get back is definitely going

202
09:39.480 --> 09:41.463
to contain some sort of rain.

203
09:44.400 --> 09:46.620
Now if we look at their hourly data,

204
09:46.620 --> 09:48.450
you can see that the weather

205
09:48.450 --> 09:51.780
is basically just rain, rain, rain.

206
09:51.780 --> 09:55.020
So between looking at places which are sunny

207
09:55.020 --> 09:58.020
and places which are rainy, you should be able

208
09:58.020 --> 09:59.370
to get your code to work,

209
09:59.370 --> 10:02.610
so that it tells you in the next 12 hours,

210
10:02.610 --> 10:07.350
if any of those condition codes are less than 700,

211
10:07.350 --> 10:10.263
which means it's got some form of precipitation.

212
10:11.310 --> 10:13.173
Pause the video and give this a go.

213
10:18.300 --> 10:22.290
All right, so let's narrow down into this weather.

214
10:22.290 --> 10:24.090
If we want to get the weather,

215
10:24.090 --> 10:28.320
then we have to tap into the first item in our list

216
10:28.320 --> 10:30.030
and then we get hold of the weather

217
10:30.030 --> 10:32.010
and then we get hold of the first item

218
10:32.010 --> 10:37.010
in that list. Under the id key, we'll get the actual value.

219
10:37.050 --> 10:40.050
We've talked about this in detail in previous lessons.

220
10:40.050 --> 10:42.030
If you've skipped a lot of lessons

221
10:42.030 --> 10:43.860
and you've come here directly,

222
10:43.860 --> 10:46.050
then it's going to be a little bit confusing

223
10:46.050 --> 10:48.630
and I recommend to review the previous lessons

224
10:48.630 --> 10:50.580
before you continue.

225
10:50.580 --> 10:53.820
Instead of printing the weather data, let's drill down.

226
10:53.820 --> 10:56.250
Let's get to the first item here.

227
10:56.250 --> 10:58.650
If we provide a set of square brackets

228
10:58.650 --> 11:00.630
and then we can access the value

229
11:00.630 --> 11:04.500
inside the list key, like this.

230
11:04.500 --> 11:08.910
And now, we've got a list with all of the hourly data

231
11:08.910 --> 11:11.613
and it looks pretty much like this.

232
11:12.780 --> 11:14.250
Now, you can confirm this

233
11:14.250 --> 11:17.790
by also pasting this into the JSON Viewer,

234
11:17.790 --> 11:20.460
replacing the previous text that was there.

235
11:20.460 --> 11:24.330
You can see we now have our items in this list.

236
11:24.330 --> 11:25.650
To drill further down,

237
11:25.650 --> 11:28.260
let's get hold of the first item in that list

238
11:28.260 --> 11:30.960
by providing a square bracket

239
11:30.960 --> 11:33.990
and then the index, which is zero.

240
11:33.990 --> 11:36.660
Now, we are into the first item

241
11:36.660 --> 11:39.120
and this is what the data looks like.

242
11:39.120 --> 11:40.980
It's a lot shorter.

243
11:40.980 --> 11:44.820
Now, we want to tap into the weather condition,

244
11:44.820 --> 11:47.340
so that means yet another set of square brackets

245
11:47.340 --> 11:50.823
and then the name of the key, which is weather.

246
11:52.560 --> 11:53.730
Now, it's pretty simple.

247
11:53.730 --> 11:58.470
It's simply giving us a list with only one item.

248
11:58.470 --> 12:02.820
Let's tap into that one item by using again,

249
12:02.820 --> 12:05.070
square brackets, zero.

250
12:05.070 --> 12:10.070
And now, we've got just a simple dictionary, essentially.

251
12:10.470 --> 12:12.330
So if we want to get hold of the id,

252
12:12.330 --> 12:15.570
then it's the final square bracket

253
12:15.570 --> 12:18.450
and the key, which is id.

254
12:18.450 --> 12:21.690
Now, what if I created a new list

255
12:21.690 --> 12:24.600
that contains the condition codes?

256
12:24.600 --> 12:26.610
We know that we've got a list

257
12:26.610 --> 12:31.470
of all of the weather conditions for the next 12 hours.

258
12:31.470 --> 12:36.470
How can we loop through that list to find out the actual id

259
12:36.780 --> 12:39.873
of the weather condition for each of those hours?

260
12:40.770 --> 12:42.570
Well, we can create a for loop

261
12:42.570 --> 12:46.590
that looks at each of the data from the hour.

262
12:46.590 --> 12:50.640
So, 'for hour_data in weather_data["list"]',

263
12:50.640 --> 12:53.070
so this is going to go through the 12 hours.

264
12:53.070 --> 12:56.220
And then for each, we're going to tap into the hour data

265
12:56.220 --> 12:58.830
and try to get hold of the item

266
12:58.830 --> 13:01.653
that is in the weather key,

267
13:03.510 --> 13:04.413
like this.

268
13:05.370 --> 13:09.180
Now, I'm going to print each of these

269
13:09.180 --> 13:12.360
and you can see, we've now got a list

270
13:12.360 --> 13:17.360
of all of the weather conditions for each of those hours.

271
13:17.760 --> 13:20.790
Now, let's narrow down that a little bit further.

272
13:20.790 --> 13:24.300
Let's get hold of the first item of each of these lists.

273
13:24.300 --> 13:26.580
And you can see, in fact, there's only one item

274
13:26.580 --> 13:27.930
in all of these lists.

275
13:27.930 --> 13:31.200
It's very rare that you have multiple weather conditions

276
13:31.200 --> 13:32.463
for each hour.

277
13:33.420 --> 13:36.420
Now that gives us a Python dictionary

278
13:36.420 --> 13:38.100
for each of those hours

279
13:38.100 --> 13:41.310
and we can tap into that final value we're interested in

280
13:41.310 --> 13:43.800
under the key id.

281
13:43.800 --> 13:47.760
So now, we've looped through the next 12 hours

282
13:47.760 --> 13:51.810
and got hold of the weather condition id

283
13:51.810 --> 13:53.223
for each of those hours.

284
13:54.120 --> 13:57.870
Now, all we need to do is to save this,

285
13:57.870 --> 14:02.870
instead of printing it, and we'll call it the condition_code.

286
14:02.871 --> 14:06.270
(keyboard typing)

287
14:06.270 --> 14:07.710
And remember previously we said

288
14:07.710 --> 14:11.340
that if the condition code is less than 700,

289
14:11.340 --> 14:15.000
then we're going to print, "Bring an umbrella".

290
14:15.000 --> 14:17.940
So we can check if condition_code,

291
14:17.940 --> 14:21.540
which remember at this point is still a string.

292
14:21.540 --> 14:25.350
So we have to turn that into an integer

293
14:25.350 --> 14:29.010
in order to be able to compare it against another number.

294
14:29.010 --> 14:33.570
If that condition_code as an integer is less than 700,

295
14:33.570 --> 14:37.173
then we're going to print, "Bring an umbrella".

296
14:39.510 --> 14:42.420
And you can see that for the next 12 hours,

297
14:42.420 --> 14:46.470
there's rain at this particular place in Lodz in Poland

298
14:46.470 --> 14:49.860
that I've put into the latitude and longitude.

299
14:49.860 --> 14:51.270
Now, if I don't want

300
14:51.270 --> 14:54.720
to call this print statement many times,

301
14:54.720 --> 14:57.718
then we can define a variable outside the for loop

302
14:57.718 --> 14:59.135
called will_rain,

303
15:00.000 --> 15:03.180
and we can set that to false to begin with.

304
15:03.180 --> 15:06.570
Now if during the next 12 hours the condition_code

305
15:06.570 --> 15:08.310
is less than 700,

306
15:08.310 --> 15:12.540
then we'll switch that to equal true instead.

307
15:12.540 --> 15:16.140
Now, after the for loop has completed,

308
15:16.140 --> 15:17.850
then we can check to see

309
15:17.850 --> 15:20.130
if it will_rain in the next 12 hours,

310
15:20.130 --> 15:22.503
and if so, it will print, "Bring an umbrella".

311
15:23.760 --> 15:26.790
This way we'll only get one print statement being called,

312
15:26.790 --> 15:28.560
instead of every single time

313
15:28.560 --> 15:32.280
we land on a condition_code for rain.

314
15:32.280 --> 15:36.330
So this involved quite a bit of JSON passing

315
15:36.330 --> 15:41.330
and also understanding how to work with parameters and APIs.

316
15:41.970 --> 15:44.490
Now, I hope you managed to get this far by yourself,

317
15:44.490 --> 15:47.370
but if not, be sure to review what I've written

318
15:47.370 --> 15:49.710
and fix your code as required.

319
15:49.710 --> 15:51.330
If any of it was confusing,

320
15:51.330 --> 15:54.570
be sure to review previous lessons before you continue

321
15:54.570 --> 15:56.340
because we're now building heavily

322
15:56.340 --> 15:57.870
on your previous knowledge

323
15:57.870 --> 16:00.390
that you learned through the course.

324
16:00.390 --> 16:01.800
Now, in the next lesson,

325
16:01.800 --> 16:03.930
we're going to be looking at how we can,

326
16:03.930 --> 16:06.600
instead of printing, "Bring an umbrella",

327
16:06.600 --> 16:09.870
to send an SMS text message

328
16:09.870 --> 16:12.993
that notifies you to bring an umbrella instead.

329
16:13.860 --> 16:15.960
So for all of that and more,

330
16:15.960 --> 16:17.560
I'll see you on the next lesson.