1
00:00:00,510 --> 00:00:02,700
Instructor: Now that we've tested our code

2
00:00:02,700 --> 00:00:05,340
and we've managed to get it working locally,

3
00:00:05,340 --> 00:00:08,730
the next step is to put our script online

4
00:00:08,730 --> 00:00:10,950
so that it can be run on schedule

5
00:00:10,950 --> 00:00:13,380
and we don't have to manually open up Python

6
00:00:13,380 --> 00:00:16,020
and run it every morning at 7:00 AM.

7
00:00:16,020 --> 00:00:16,950
How do we do this?

8
00:00:16,950 --> 00:00:18,750
Well, we're going to use PythonAnywhere,

9
00:00:18,750 --> 00:00:20,970
the same service that we used before

10
00:00:20,970 --> 00:00:24,420
when we created the automatic birthday wisher.

11
00:00:24,420 --> 00:00:26,430
Now, the first thing we're going to do is, of course,

12
00:00:26,430 --> 00:00:27,540
log into the service

13
00:00:27,540 --> 00:00:30,300
and we're going to delete all of our previous files,

14
00:00:30,300 --> 00:00:33,990
so that includes the letter template folder

15
00:00:33,990 --> 00:00:37,443
and also the main.py and the birthday.csv.

16
00:00:39,990 --> 00:00:42,450
Now instead of the previous main.py,

17
00:00:42,450 --> 00:00:45,270
we're going to upload our latest main.py.

18
00:00:45,270 --> 00:00:49,353
So let's go ahead and locate this in our computer.

19
00:00:50,400 --> 00:00:53,133
And then we're going to upload it to PythonAnywhere.

20
00:00:55,710 --> 00:00:56,910
There you go.

21
00:00:56,910 --> 00:01:01,910
Now let's open up this file and click Bash console here.

22
00:01:02,250 --> 00:01:05,253
So that's going to create our console down at the bottom,

23
00:01:07,080 --> 00:01:09,150
and once it's ready like this,

24
00:01:09,150 --> 00:01:11,940
we can enter the command to run this code.

25
00:01:11,940 --> 00:01:15,210
So it's python3, and then it's the name of our file,

26
00:01:15,210 --> 00:01:17,850
which is main.py.

27
00:01:17,850 --> 00:01:21,180
And because it's directly within my user's folder,

28
00:01:21,180 --> 00:01:24,210
I don't have to specify a file path to it.

29
00:01:24,210 --> 00:01:26,820
Now, I don't recommend to have your main.py nested

30
00:01:26,820 --> 00:01:29,670
within other folders because it's going to make this

31
00:01:29,670 --> 00:01:31,410
a little bit more complicated.

32
00:01:31,410 --> 00:01:33,630
So as long as you've uploaded it to the same place

33
00:01:33,630 --> 00:01:36,510
that I have, just straight after your username,

34
00:01:36,510 --> 00:01:38,910
then we should be able to run this line of code.

35
00:01:40,530 --> 00:01:43,980
And we can test out whether if this code now works

36
00:01:43,980 --> 00:01:45,980
when it's being run from PythonAnywhere.

37
00:01:46,830 --> 00:01:51,120
Now what you'll see instead of the message status, however,

38
00:01:51,120 --> 00:01:55,650
is a exception, and it's a connection error.

39
00:01:55,650 --> 00:01:57,930
And the connection error tells us something

40
00:01:57,930 --> 00:02:02,930
about this api.twilio max retries exceeded with url.

41
00:02:04,440 --> 00:02:08,400
So if we go ahead and highlight that, which we'll copy it,

42
00:02:08,400 --> 00:02:10,470
then we can paste it into Google

43
00:02:10,470 --> 00:02:12,600
and figure out what's wrong.

44
00:02:12,600 --> 00:02:15,630
The first post you can see is a post

45
00:02:15,630 --> 00:02:17,283
from Help at PythonAnywhere.

46
00:02:18,150 --> 00:02:20,340
And they've created this post to tell you

47
00:02:20,340 --> 00:02:21,660
how to get Twilio to work

48
00:02:21,660 --> 00:02:24,333
on free accounts with PythonAnywhere.

49
00:02:25,530 --> 00:02:27,330
As they say, if you're trying to use Twilio

50
00:02:27,330 --> 00:02:29,520
on a PythonAnywhere free account,

51
00:02:29,520 --> 00:02:30,630
you're going to run into an error

52
00:02:30,630 --> 00:02:32,160
that looks something like this,

53
00:02:32,160 --> 00:02:33,840
which is exactly what we got.

54
00:02:33,840 --> 00:02:35,940
And that's where Google Search picked it up

55
00:02:35,940 --> 00:02:37,443
to show us this article.

56
00:02:38,340 --> 00:02:41,190
The reason for this is because the Twilio API

57
00:02:41,190 --> 00:02:43,560
basically needs to be told how to connect

58
00:02:43,560 --> 00:02:47,280
to the proxy servers that free accounts use.

59
00:02:47,280 --> 00:02:50,340
When you have a paid account on PythonAnywhere,

60
00:02:50,340 --> 00:02:53,580
you have an actual address to your dedicated server,

61
00:02:53,580 --> 00:02:55,860
but when you only sign up with a free account

62
00:02:55,860 --> 00:02:59,580
like we have here, we only get a proxy server.

63
00:02:59,580 --> 00:03:01,740
So we need to change the code a little bit

64
00:03:01,740 --> 00:03:03,063
in order for it to work.

65
00:03:03,930 --> 00:03:06,570
Even though we are actually using the latest version

66
00:03:06,570 --> 00:03:08,700
of Twilio, from testing I found

67
00:03:08,700 --> 00:03:11,100
that this code doesn't seem to work for me.

68
00:03:11,100 --> 00:03:14,460
Instead, we have to use this version of the fix

69
00:03:14,460 --> 00:03:16,680
that they've specified here.

70
00:03:16,680 --> 00:03:19,740
So the only difference from their version of the code

71
00:03:19,740 --> 00:03:24,600
and what we have here in our main.py is three lines of code.

72
00:03:24,600 --> 00:03:28,740
First, we have to import this class called TwilioHttpClient

73
00:03:28,740 --> 00:03:30,450
from the Twilio module.

74
00:03:30,450 --> 00:03:34,083
So let's copy that and paste it below our previous lines.

75
00:03:35,460 --> 00:03:39,330
Now in addition, we have to create a proxy client

76
00:03:39,330 --> 00:03:41,790
with the TwilioHttpClient class

77
00:03:41,790 --> 00:03:44,310
that we just imported just now.

78
00:03:44,310 --> 00:03:46,740
So we're going to put that in our IF statement

79
00:03:46,740 --> 00:03:49,860
when we're about to create our SMS message.

80
00:03:49,860 --> 00:03:51,300
The last step is,

81
00:03:51,300 --> 00:03:54,630
where we have our client class being created,

82
00:03:54,630 --> 00:03:58,080
we have to set this HTTP client parameter

83
00:03:58,080 --> 00:04:00,663
to the proxy client that we created just now.

84
00:04:01,620 --> 00:04:04,020
That's going to go right here.

85
00:04:04,020 --> 00:04:06,600
The rest of the code, we can leave as is,

86
00:04:06,600 --> 00:04:10,623
and we can simply hit Save to update that code.

87
00:04:11,580 --> 00:04:13,530
Now once we've typed all of that code,

88
00:04:13,530 --> 00:04:15,900
you can see we get an error in here.

89
00:04:15,900 --> 00:04:18,269
It says undefined name os,

90
00:04:18,269 --> 00:04:22,560
and that's because this os actually comes from an os module,

91
00:04:22,560 --> 00:04:26,193
so we should import that in order for this error to go away.

92
00:04:27,090 --> 00:04:29,220
So let's hit Save again,

93
00:04:29,220 --> 00:04:33,060
and you can see we are now free of warnings and errors.

94
00:04:33,060 --> 00:04:35,700
We're now ready to go into our console

95
00:04:35,700 --> 00:04:39,510
and to run the same command again, which is python3

96
00:04:39,510 --> 00:04:42,600
and then it's the name of our file, main.py.

97
00:04:42,600 --> 00:04:44,130
So now when we hit enter,

98
00:04:44,130 --> 00:04:46,470
you can see we get back the message queued,

99
00:04:46,470 --> 00:04:48,390
which comes from this print statement,

100
00:04:48,390 --> 00:04:50,610
and that's because the status of our message

101
00:04:50,610 --> 00:04:52,323
has now been queued.

102
00:04:53,190 --> 00:04:57,510
And you can see I've now received the message from Twilio,

103
00:04:57,510 --> 00:05:00,300
and this is, of course, because my main.py was run

104
00:05:00,300 --> 00:05:02,100
on the PythonAnywhere servers

105
00:05:02,100 --> 00:05:04,560
instead of from my local computer.

106
00:05:04,560 --> 00:05:06,990
So now that we've confirmed that this works,

107
00:05:06,990 --> 00:05:09,430
we can now finally go back to PythonAnywhere

108
00:05:11,100 --> 00:05:16,100
and go to the Tasks section in order to set up our task.

109
00:05:16,920 --> 00:05:19,890
Now here, I've still got my previous task set up

110
00:05:19,890 --> 00:05:23,310
when we created the automatic birthday wisher.

111
00:05:23,310 --> 00:05:24,480
Now, because I'm demoing this

112
00:05:24,480 --> 00:05:27,030
with a free PythonAnywhere account,

113
00:05:27,030 --> 00:05:30,150
I can only create one scheduled task.

114
00:05:30,150 --> 00:05:32,370
If I start paying them, then I can schedule

115
00:05:32,370 --> 00:05:35,580
as many as I want and they never expire.

116
00:05:35,580 --> 00:05:37,380
But because we're just learning here,

117
00:05:37,380 --> 00:05:39,690
I don't want you to commit to a paid account

118
00:05:39,690 --> 00:05:41,730
just to be able to see how it works.

119
00:05:41,730 --> 00:05:44,400
So we're going to use the same scheduled task.

120
00:05:44,400 --> 00:05:46,110
Now, if you don't have any task scheduled,

121
00:05:46,110 --> 00:05:48,000
just go ahead and create one,

122
00:05:48,000 --> 00:05:49,770
and the command is going to be the same.

123
00:05:49,770 --> 00:05:53,070
It's python3, and then it's running our main.py.

124
00:05:53,070 --> 00:05:56,280
So the same command that you entered previously.

125
00:05:56,280 --> 00:05:58,980
And we're going to set the frequency to daily,

126
00:05:58,980 --> 00:06:01,383
and it's going to run at 7:00 AM every day.

127
00:06:02,460 --> 00:06:05,460
In order to test this, I'm going to change the time

128
00:06:05,460 --> 00:06:08,670
from 7:00 AM to the current time.

129
00:06:08,670 --> 00:06:11,910
So the current server time is registering as 10:01,

130
00:06:11,910 --> 00:06:14,280
but, in fact, I'm actually seeing 02,

131
00:06:14,280 --> 00:06:17,850
so I'm going to change that to 10:03,

132
00:06:17,850 --> 00:06:20,850
and then hit the check mark.

133
00:06:20,850 --> 00:06:24,030
And now I'm going to wait patiently to see

134
00:06:24,030 --> 00:06:27,120
if that is going to be triggered automatically

135
00:06:27,120 --> 00:06:28,680
from the scheduled tasks,

136
00:06:28,680 --> 00:06:30,783
and I get the SMS sent to my phone.

137
00:06:32,010 --> 00:06:33,270
And there you have it.

138
00:06:33,270 --> 00:06:36,000
This is now being sent to me from Twilio

139
00:06:36,000 --> 00:06:37,950
because we made the API call,

140
00:06:37,950 --> 00:06:41,850
but it's being sent because I've got this scheduled task,

141
00:06:41,850 --> 00:06:46,680
which is calling this command in order to run our main.py.

142
00:06:46,680 --> 00:06:49,800
And it's being done at a time which I've specified,

143
00:06:49,800 --> 00:06:51,750
which in fact I want to happen

144
00:06:51,750 --> 00:06:54,570
at, probably, 7:00 AM in the morning.

145
00:06:54,570 --> 00:06:56,790
Now, notice that this is UTC time.

146
00:06:56,790 --> 00:07:01,470
So if you want to convert the UTC time to your local time,

147
00:07:01,470 --> 00:07:05,010
so at the moment we're on British Summer Time where I'm at,

148
00:07:05,010 --> 00:07:06,720
then you can type this into Google

149
00:07:06,720 --> 00:07:10,170
and change this to whatever time zone you are in.

150
00:07:10,170 --> 00:07:14,250
And that way you can figure out what time UTC is

151
00:07:14,250 --> 00:07:17,040
relative to your local time.

152
00:07:17,040 --> 00:07:19,440
In my case, it's just one hour behind.

153
00:07:19,440 --> 00:07:22,530
So if I want this to run at 7:00 AM my local time,

154
00:07:22,530 --> 00:07:25,560
then I have to change this to 6:00.

155
00:07:25,560 --> 00:07:28,140
And now that's going to run every day at 6:00 AM

156
00:07:28,140 --> 00:07:30,180
without me needing to do anything.

157
00:07:30,180 --> 00:07:33,210
And I'm going to get my notification on time

158
00:07:33,210 --> 00:07:34,593
if it's going to rain.

