forked from mattmakai/fullstackpython.com
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathall.atom.xml
More file actions
2478 lines (2171 loc) · 210 KB
/
all.atom.xml
File metadata and controls
2478 lines (2171 loc) · 210 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Full Stack Python</title><link href="https://www.fullstackpython.com/" rel="alternate"></link><link href="https://www.fullstackpython.com/feeds/all.atom.xml" rel="self"></link><id>https://www.fullstackpython.com/</id><updated>2016-11-23T00:00:00-05:00</updated><entry><title>How to Make Phone Calls in Python</title><link href="https://www.fullstackpython.com/make-phone-calls-python.html" rel="alternate"></link><updated>2016-11-23T00:00:00-05:00</updated><author><name>Matt Makai</name></author><id>tag:www.fullstackpython.com,2016-11-23:make-phone-calls-python.html</id><summary type="html"><p>Good old-fashioned phone calls remain one of the best forms of communication
despite the slew of new smartphone apps that have popped up over the past
several years. With just a few lines of Python code plus a
<a href="/application-programming-interfaces.html">web application programming interface</a>
we can make and receive phone calls from any application. </p>
<p>Our example calls will say a snippet of text and put all incoming callers
into a recorded conference call. You can modify the instructions using
<a href="https://www.twilio.com/docs/api/twiml">Twilio's TwiML verbs</a> when you
perform different actions in your own application's phone calls.</p>
<h2>Our Tools</h2>
<p>You should have either <a href="/python-2-or-3.html">Python 2 or 3</a> installed to
build this application. Throughout the post we will also use:</p>
<ul>
<li><a href="https://pip.pypa.io/en/stable/">pip</a> and
<a href="https://virtualenv.pypa.io/en/latest/">virtualenv</a> to handle
<a href="/application-dependencies.html">application dependencies</a></li>
<li>A free <a href="https://www.twilio.com/try-twilio">Twilio account</a> to use their
<a href="https://www.twilio.com/docs/api/rest/making-calls">phone calling web API</a></li>
<li>Twilio's
<a href="https://www.twilio.com/docs/libraries/python">Python helper library</a>,
which is <a href="https://pypi.python.org/pypi/twilio">available on PyPI</a></li>
</ul>
<p>You can snag all the open source code for this tutorial in the
<a href="https://github.com/mattmakai/python-twilio-example-apps/tree/master/no-framework/phone-calls">python-twilio-example-apps</a>
GitHub repository under the
<a href="https://github.com/mattmakai/python-twilio-example-apps/tree/master/no-framework/phone-calls">no-framework/phone-calls</a> directory.
Use and copy the code for your own applications. Everything in that
repository and in this blog post are open source under the MIT license.</p>
<h2>Install App Dependencies</h2>
<p>Our application will use the <a href="/twilio.html">Twilio</a>
<a href="https://www.twilio.com/docs/libraries/python">Python helper library</a>
to create an HTTP POST request to Twilio's API. The Twilio helper library is
installable from <a href="https://pypi.python.org/pypi">PyPI</a> into a virtual
environment. Open your terminal and use the <code>virtualenv</code> command to create
a new virtualenv:</p>
<div class="highlight"><pre>virtualenv phoneapp
</pre></div>
<p>Invoke the <code>activate</code> script within the virtualenv <code>bin/</code> directory to make
this virtualenv the active Python executable. Note that you will need to
perform this step in every terminal window that you want the virtualenv to
be active.</p>
<div class="highlight"><pre>source phoneapp/bin/activate
</pre></div>
<p>The command prompt will change after activating the virtualenv
to something like <code>(phoneapp) $</code>. </p>
<p>Next use the <code>pip</code> command to install the
<a href="https://www.twilio.com/docs/libraries/python">Twilio Python</a> package
into the virtualenv.</p>
<div class="highlight"><pre>pip install twilio
</pre></div>
<p>We will have the required dependency ready for project as soon as the
installation script finishes. Now we can write and execute Python code to
dial phone numbers.</p>
<h2>Our Python Script</h2>
<p>Create a new file named <code>phone_calls.py</code> and copy or type in the following
lines of code.</p>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">twilio.rest</span> <span class="kn">import</span> <span class="n">TwilioRestClient</span>
<span class="c"># Twilio phone number goes here. Grab one at https://twilio.com/try-twilio</span>
<span class="c"># and use the E.164 format, for example: &quot;+12025551234&quot;</span>
<span class="n">TWILIO_PHONE_NUMBER</span> <span class="o">=</span> <span class="s">&quot;&quot;</span>
<span class="c"># list of one or more phone numbers to dial, in &quot;+19732644210&quot; format</span>
<span class="n">DIAL_NUMBERS</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;&quot;</span><span class="p">,]</span>
<span class="c"># URL location of TwiML instructions for how to handle the phone call</span>
<span class="n">TWIML_INSTRUCTIONS_URL</span> <span class="o">=</span> \
<span class="s">&quot;http://static.fullstackpython.com/phone-calls-python.xml&quot;</span>
<span class="c"># replace the placeholder values with your Account SID and Auth Token</span>
<span class="c"># found on the Twilio Console: https://www.twilio.com/console</span>
<span class="n">client</span> <span class="o">=</span> <span class="n">TwilioRestClient</span><span class="p">(</span><span class="s">&quot;ACxxxxxxxxxx&quot;</span><span class="p">,</span> <span class="s">&quot;yyyyyyyyyy&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">dial_numbers</span><span class="p">(</span><span class="n">numbers_list</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Dials one or more phone numbers from a Twilio phone number.&quot;&quot;&quot;</span>
<span class="k">for</span> <span class="n">number</span> <span class="ow">in</span> <span class="n">numbers_list</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;Dialing &quot;</span> <span class="o">+</span> <span class="n">number</span><span class="p">)</span>
<span class="c"># set the method to &quot;GET&quot; from default POST because Amazon S3 only</span>
<span class="c"># serves GET requests on files. Typically POST would be used for apps</span>
<span class="n">client</span><span class="o">.</span><span class="n">calls</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">to</span><span class="o">=</span><span class="n">number</span><span class="p">,</span> <span class="n">from_</span><span class="o">=</span><span class="n">TWILIO_PHONE_NUMBER</span><span class="p">,</span>
<span class="n">url</span><span class="o">=</span><span class="n">TWIML_INSTRUCTIONS_URL</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&quot;GET&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span>
<span class="n">dial_numbers</span><span class="p">(</span><span class="n">DIAL_NUMBERS</span><span class="p">)</span>
</pre></div>
<p>There are a few lines that you need to modify in this application before it
will run. First, insert one or more phone numbers you wish to dial into the
DIAL_NUMBERS list. Each one should be a string, separated by a comma. For
example, <code>DIAL_NUMBERS = ["+12025551234", "+14155559876", "+19735551234"]</code>.</p>
<p>Next, <code>TWILIO_PHONE_NUMBER</code> and the Account SID and Authentication Token,
found on the <code>client = TwilioRestClient("ACxxxxxxxxxx", "yyyyyyyyyy")</code>
line, need to be set. We can get these values from the
<a href="https://www.twilio.com/console">Twilio Console</a>.</p>
<p>In your web browser go to the
<a href="https://www.twilio.com/try-twilio">Twilio website and sign up for a free account</a>
or sign into your existing Twilio account.</p>
<p><img src="/source/static/img/161123-python-phone-calls/try-twilio.png" width="100%" class="technical-diagram img-rounded" alt="Twilio sign up screen."></p>
<p>Copy the Account SID and Auth Token from the Twilio Console and paste them
into your application's code: </p>
<p><img src="/source/static/img/161123-python-phone-calls/twilio-console-tokens.png" width="100%" class="technical-diagram img-rounded" alt="Obtain the Account SID and Auth Token from the Twilio Console."></p>
<p>The Twilio trial account allows you to dial and receive phone calls to
your own validated phone number. To handle calls from any phone
number then you need to upgrade your account (hit the upgrade button on the
top navigation bar). </p>
<p>Once you are signed into your Twilio account, go to the
<a href="https://www.twilio.com/console/phone-numbers">manage phone numbers screen</a>.
On this screen you can
<a href="https://www.twilio.com/console/phone-numbers/search">buy one or more phone numbers</a>
or click on an existing phone number in your account to configure it.</p>
<p><img src="/source/static/img/161123-python-phone-calls/manage-numbers.jpg" width="100%" class="technical-diagram img-rounded" alt="Manage phone numbers screen."></p>
<p>After clicking on a number you will reach the phone number configuration
screen. Paste in the URL with TwiML instructions and change the dropdown from
"HTTP POST" to "HTTP GET". In this post we'll use
<code>http://static.fullstackpython.com/phone-calls-python.xml</code>, but that URL
can be more than just a static XML file. </p>
<p><img src="/source/static/img/161123-python-phone-calls/twiml-url-number-screen.jpg" width="100%" class="technical-diagram img-rounded" alt="Twilio phone number configuration screen."></p>
<p>The power of Twilio really comes in when that URL is handled by your web
application so it can dynamically respond with TwiML instructions based on
the incoming caller number or other properties stored in your database.</p>
<p>Under the Voice webhook, paste in
<code>http://static.fullstackpython.com/phone-calls-python.xml</code> and change the
drop-down to the right from "HTTP POST" to "HTTP GET". Click the "Save"
button at the bottom of the screen.</p>
<p>Now try calling your phone number. You should hear the snippet of text
read by the Alice voice and then you will be placed into a conference call.
If no one else calls the number then hold music should be playing.</p>
<h2>Making Phone Calls</h2>
<p>We just handled inbound phone calls to our phone number. Now it's time to
dial outbound phone calls. Make sure your <code>phone_calls.py</code> file is saved
and that your virtualenv is still activated and then execute the script:</p>
<div class="highlight"><pre>python phone_calls.py
</pre></div>
<p>In a moment all the phone numbers you write in the <code>DIAL_NUMBERS</code> list
should light up with calls. Anyone that answers will hear our message read
by the "Alice" voice and then they'll be placed together into a recorded
conference call, just like when someone dials into the number. </p>
<p>Here is my inbound phone call:</p>
<p><img src="/source/static/img/161123-python-phone-calls/inbound-call.png" width="100%" class="technical-diagram img-rounded" alt="Receiving an incoming phone call on the iPhone."></p>
<p>Not bad for just a few lines of Python code!</p>
<h2>Next Steps</h2>
<p>Now that we know how to make and receive phone calls from a Twilio number
that follows programmatic instructions we can do a whole lot more in our
applications. Next you can use out one of these tutorials to do more with
the phone number:</p>
<ul>
<li><a href="https://www.twilio.com/blog/2016/05/add-phone-calling-slack-python.html">Build a phone-calling Slack bot</a></li>
<li><a href="https://www.twilio.com/docs/tutorials/walkthrough/masked-numbers/python/flask">Mask phone numbers for anonymous communication</a></li>
<li><a href="https://www.twilio.com/docs/tutorials/walkthrough/call-tracking/python/django">Add call tracking to see metrics for phone calls</a></li>
</ul>
<p>Questions? Contact me via Twitter
<a href="https://twitter.com/fullstackpython">@fullstackpython</a>
or <a href="https://twitter.com/mattmakai">@mattmakai</a>. I'm also on GitHub as
<a href="https://github.com/mattmakai">mattmakai</a>.</p>
<p>Something wrong with this post? Fork
<a href="https://github.com/mattmakai/fullstackpython.com/blob/gh-pages/source/content/posts/161123-make-phone-calls.markdown">this page's source on GitHub</a>.</p></summary></entry><entry><title>Dialing Outbound Phone Calls with a Bottle Web App</title><link href="https://www.fullstackpython.com/dial-outbound-phone-calls-python-bottle.html" rel="alternate"></link><updated>2016-10-27T00:00:00-04:00</updated><author><name>Matt Makai</name></author><id>tag:www.fullstackpython.com,2016-08-30:dial-outbound-phone-calls-python-bottle.html</id><summary type="html"><p>Python web apps built with the <a href="/bottle.html">Bottle web framework</a> can
<a href="/blog/send-sms-text-messages-python.html">send</a> and
<a href="/blog/reply-sms-text-messages-python-bottle.html">receive SMS text messages</a>.
In this tutorial we will go beyond texting and learn how to dial outbound
phone calls. The calls will read a snippet of text then play an MP3 file,
but they can then be easily modified to create conference lines and many
other voice features in your Python web apps.</p>
<h2>Tools We Need</h2>
<p>You should have either <a href="/python-2-or-3.html">Python 2 or 3</a> installed to
create your Bottle app, although Python 3 is recommended for new
applications. We also need:</p>
<ul>
<li><a href="https://pip.pypa.io/en/stable/">pip</a> and
<a href="https://virtualenv.pypa.io/en/latest/">virtualenv</a> to handle
<a href="/application-dependencies.html">application dependencies</a></li>
<li><a href="https://ngrok.com/">Ngrok</a> for localhost tunneling to our Bottle
application while it's running on our local development environment</li>
<li><a href="/bottle.html">Bottle</a> web framework</li>
<li>Free <a href="https://www.twilio.com/try-twilio">Twilio account</a> to use their
<a href="https://www.twilio.com/docs/api/rest/making-calls">phone calling web API</a></li>
<li>Twilio's
<a href="https://www.twilio.com/docs/libraries/python">Python helper library</a>,
which is <a href="https://github.com/twilio/twilio-python">open source on GitHub</a>
and <a href="https://pypi.python.org/pypi/twilio">available for download from PyPI</a></li>
</ul>
<p>Take a look at
<a href="/blog/python-3-bottle-gunicorn-ubuntu-1604-xenial-xerus.html">this guide on setting up Python 3, Bottle and Gunicorn on Ubuntu 16.04 LTS</a>
if you need help getting your
<a href="/development-environments.html">development environment</a>
configured before continuing on through the remainder of this tutorial.</p>
<p>You can snag all the open source code for this tutorial in the
<a href="https://github.com/mattmakai/python-bottle-phone">python-bottle-phone</a>
GitHub repository under the
<a href="https://github.com/mattmakai/python-bottle-phone/tree/master/outbound-calls">outbound directory</a>.
Use and copy the code however you want - it's all open source under the
MIT license.</p>
<h2>Installing Our Application Dependencies</h2>
<p>Our Bottle app needs a helper code library to make it easy to dial outbound
phone calls. Bottle and the Twilio helper library are installable from
<a href="https://pypi.python.org/pypi">PyPI</a> into a virtualenv. Open your terminal
and use the <code>virtualenv</code> command to create a new virtualenv:</p>
<div class="highlight"><pre>virtualenv bottlephone
</pre></div>
<p>Use the <code>activate</code> script within the virtualenv, which makes this virtualenv
the active Python installation. Note that you need to do this in every
terminal window that you want this virtualenv to be used.</p>
<div class="highlight"><pre>source bottlephone/bin/activate
</pre></div>
<p>The command prompt will change after activating the virtualenv
to something like <code>(bottlephone) $</code>. Here is a screenshot of what my
environment looked like when I used the <code>activate</code> script.</p>
<p><img src="/source/static/img/160830-phone-calls-bottle/activate-virtualenv.png" width="100%" class="technical-diagram img-rounded"></p>
<p>Next use the <code>pip</code> command to install the <a href="/bottle.html">Bottle</a> and
<a href="https://www.twilio.com/docs/libraries/python">Twilio Python</a> packages
into your virtualenv.</p>
<div class="highlight"><pre>pip install bottle twilio
</pre></div>
<p>After the installation script finishes, we will have the required
dependencies to build our app. Time to write some Python code to dial
outbound phone calls.</p>
<h2>Bottle and Twilio</h2>
<p>Our simple Bottle web app will have three routes: </p>
<ul>
<li><code>/</code> - returns a text string to let us know our Bottle app is running</li>
<li><code>/twiml</code> - responds with <a href="https://www.twilio.com/docs/api/twiml">TwiML</a>
(a simple subset of XML) that instructs Twilio what to do when someone
picks up the call to them from our Bottle web app</li>
<li><code>/dial-phone/&lt;outbound_phone_number&gt;</code>, where "outbound_phone_number" is
a phone number in the format "+12025551234" - this route uses the Twilio
helper library to send a POST request to the Twilio Voice API to dial a
phone call</li>
</ul>
<p>We can build the structure of our Bottle app and the first route right now.
Create a new file named <code>app.py</code> with the following contents to start our
app.</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">bottle</span>
<span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">Response</span>
<span class="kn">from</span> <span class="nn">twilio</span> <span class="kn">import</span> <span class="n">twiml</span>
<span class="kn">from</span> <span class="nn">twilio.rest</span> <span class="kn">import</span> <span class="n">TwilioRestClient</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">default_app</span><span class="p">()</span>
<span class="c"># plug in account SID and auth token here if they are not already exposed as</span>
<span class="c"># environment variables</span>
<span class="n">twilio_client</span> <span class="o">=</span> <span class="n">TwilioRestClient</span><span class="p">()</span>
<span class="n">TWILIO_NUMBER</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;TWILIO_NUMBER&#39;</span><span class="p">,</span> <span class="s">&#39;+12025551234&#39;</span><span class="p">)</span>
<span class="n">NGROK_BASE_URL</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;NGROK_BASE_URL&#39;</span><span class="p">,</span> <span class="s">&#39;https://c6c6d4e8.ngrok.io&#39;</span><span class="p">)</span>
<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">index</span><span class="p">():</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Returns a standard text response to show the app is up and running.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">Response</span><span class="p">(</span><span class="s">&quot;Bottle app running!&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
<span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">&#39;127.0.0.1&#39;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8000</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">reloader</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
</pre></div>
<p>Make sure you are in the directory where you created the above <code>app.py</code>
file. Run the app via the Bottle development server with the following
command. Make sure your virtualenv is still activated so our code can rely
on the Bottle code library.</p>
<div class="highlight"><pre>python app.py
</pre></div>
<p>We should see a successful development server start up like this:</p>
<div class="highlight"><pre>(bottlephone) matt@ubuntu:~/bottlephone$ python app.py
Bottle v0.12.9 server starting up (using WSGIRefServer())...
Listening on http://127.0.0.1:8000/
Hit Ctrl-C to quit.
</pre></div>
<p>Here is what the development server message looks like in my environment
on Ubuntu:</p>
<p><img src="/source/static/img/160830-phone-calls-bottle/bottle-app-running.png" width="100%" class="technical-diagram img-rounded" alt="Successfully starting the Bottle development server from the command line."></p>
<p>Let's test out the app by going to <a href="http://localhost:8000">localhost:8000</a>
in the web browser. We should get a simple success message that the app
is running and responding to requests.</p>
<p><img src="/source/static/img/160830-phone-calls-bottle/bottle-app-web-browser.png" width="100%" class="technical-diagram img-rounded" alt="Simple success message in the web browser that the Bottle app is running."></p>
<p>Next we need to obtain a phone number that our Bottle app can use to
call other phone numbers.</p>
<h2>Obtain a Phone Number</h2>
<p>Our basic Bottle web app is running but what we really want to do is dial
outbound calls - which will be handled by <a href="https://www.twilio.com/">Twilio</a>.</p>
<p>In your web browser go to the
<a href="https://www.twilio.com/try-twilio">Twilio website and sign up for a free account</a>.
You can also sign into your existing Twilio account if you already have one.</p>
<p><img src="/source/static/img/160830-phone-calls-bottle/try-twilio.png" width="100%" class="technical-diagram img-rounded" alt="Twilio sign up screen."></p>
<p>The Twilio trial account allows you to dial and receive phone calls to
your own validated phone number. To dial and receive calls from any phone
number then you need to upgrade your account (hit the upgrade button on the
top navigation bar to do that). Trial accounts are great for initial
development before your application goes live but upgraded accounts are where
the real power comes in.</p>
<p>Once you are signed into your Twilio account, go to the
<a href="https://www.twilio.com/console/phone-numbers">manage phone numbers screen</a>.
On this screen you can
<a href="https://www.twilio.com/console/phone-numbers/search">buy one or more phone numbers</a>
or click on an existing phone number in your account to configure it.</p>
<p><img src="/source/static/img/160830-phone-calls-bottle/manage-phone-numbers.png" width="100%" class="technical-diagram img-rounded" alt="Manage phone numbers screen."></p>
<p>There is nothing for us to configure right now on the phone number
configuration page because we are making outbound phone calls for this
tutorial. Now that we have a phone number in hand, let's add the final bit
of code to our Bottle app to get this app working.</p>
<h2>Making Phone Calls</h2>
<p>We need to add two new routes to our Bottle app so it can dial outbound
phone calls. Modify your existing app.py file with the two new functions
below, <code>twiml_response</code> and <code>outbound_call</code>. None of the other code in
this file needs to change other than adding those two new functions to
what we wrote in the previous section.</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">bottle</span>
<span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">Response</span>
<span class="kn">from</span> <span class="nn">twilio</span> <span class="kn">import</span> <span class="n">twiml</span>
<span class="kn">from</span> <span class="nn">twilio.rest</span> <span class="kn">import</span> <span class="n">TwilioRestClient</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">default_app</span><span class="p">()</span>
<span class="c"># plug in account SID and auth token here if they are not already exposed as</span>
<span class="c"># environment variables</span>
<span class="n">twilio_client</span> <span class="o">=</span> <span class="n">TwilioRestClient</span><span class="p">()</span>
<span class="c"># add your Twilio phone number here</span>
<span class="n">TWILIO_NUMBER</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;TWILIO_NUMBER&#39;</span><span class="p">,</span> <span class="s">&#39;+16093002984&#39;</span><span class="p">)</span>
<span class="c"># plug in your Ngrok Forwarding URL - we&#39;ll set it up in a minute</span>
<span class="n">NGROK_BASE_URL</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;NGROK_BASE_URL&#39;</span><span class="p">,</span> <span class="s">&#39;https://c6c6d4e8.ngrok.io&#39;</span><span class="p">)</span>
<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">index</span><span class="p">():</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Returns a standard text response to show the app is up and running.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">Response</span><span class="p">(</span><span class="s">&quot;Bottle app running!&quot;</span><span class="p">)</span>
<span class="nd">@post</span><span class="p">(</span><span class="s">&#39;/twiml&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">twiml_response</span><span class="p">():</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Provides TwiML instructions in response to a Twilio POST webhook</span>
<span class="sd"> event so that Twilio knows how to handle the outbound phone call</span>
<span class="sd"> when someone picks up the phone.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">twiml</span><span class="o">.</span><span class="n">Response</span><span class="p">()</span>
<span class="n">response</span><span class="o">.</span><span class="n">say</span><span class="p">(</span><span class="s">&quot;Sweet, this phone call is answered by your Bottle app!&quot;</span><span class="p">)</span>
<span class="n">response</span><span class="o">.</span><span class="n">play</span><span class="p">(</span><span class="s">&quot;https://api.twilio.com/cowbell.mp3&quot;</span><span class="p">,</span> <span class="n">loop</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
<span class="k">return</span> <span class="n">Response</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">response</span><span class="p">))</span>
<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/dial-phone/&lt;outbound_phone_number&gt;&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">outbound_call</span><span class="p">(</span><span class="n">outbound_phone_number</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Uses the Twilio Python helper library to send a POST request to</span>
<span class="sd"> Twilio telling it to dial an outbound phone call from our specific</span>
<span class="sd"> Twilio phone number (that phone number must be owned by our</span>
<span class="sd"> Twilio account).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="c"># the url must match the Ngrok Forwarding URL plus the route defined in</span>
<span class="c"># the previous function that responds with TwiML instructions</span>
<span class="n">twilio_client</span><span class="o">.</span><span class="n">calls</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">to</span><span class="o">=</span><span class="n">OUTBOUND_NUMBER</span><span class="p">,</span> <span class="n">from_</span><span class="o">=</span><span class="n">BLOG_POST_NUMBER</span><span class="p">,</span>
<span class="n">url</span><span class="o">=</span><span class="n">NGROK_BASE_URL</span> <span class="o">+</span> <span class="s">&#39;/twiml&#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="n">Response</span><span class="p">(</span><span class="s">&#39;phone call placed to &#39;</span> <span class="o">+</span> <span class="n">outbound_phone_number</span> <span class="o">+</span> <span class="s">&#39;!&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
<span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">&#39;127.0.0.1&#39;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8000</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">reloader</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
</pre></div>
<p>There is just one problem with our current setup if you're developing on
a local environment: Twilio won't be able to reach that <code>/twiml</code> route.
We need to deploy our app to a reachable server, or just use a localhost
tunneling tool like <a href="https://ngrok.com">Ngrok</a>. Ngrok provides an external
URL that connects to a port running on your machine.
<a href="https://ngrok.com/download">Download and install the Ngrok application</a>
that is appropriate for your operating system.</p>
<p>We run Ngrok locally and expose our Bottle app that is running on
port 8000. Run this command within the directory where the Ngrok executable is
located.</p>
<div class="highlight"><pre>./ngrok http 8000
</pre></div>
<p>Ngrok will start up and provide us with a Forwarding URL, with both HTTP
and HTTPS versions.</p>
<p><img src="/source/static/img/160830-phone-calls-bottle/start-ngrok.png" width="100%" class="technical-diagram img-rounded" alt="Ngrok started and running to serve as a localhost tunnel."></p>
<p>We can use the Forwarding URL to instruct Twilio how to handle the outbound
phone call when someone picks up. Insert the Ngrok forwarding URL into the
<code>app.py</code> file where <code>NGROK_BASE_URL</code> is specified.</p>
<p><img src="/source/static/img/160830-phone-calls-bottle/access-ngrok.png" width="100%" class="technical-diagram img-rounded" alt="Paste the ngrok Forwarding URL into the Twilio webhook configuration text box."></p>
<p>If Ngrok is useful to you, make sure to read this
<a href="https://www.twilio.com/blog/2015/09/6-awesome-reasons-to-use-ngrok-when-testing-webhooks.html">6 awesome reasons to use Ngrok when testing webhooks post</a>
to learn even more about the tool.</p>
<p>Time to test out our app, let's give it a quick spin.</p>
<h2>Making Phone Calls</h2>
<p>Make sure your Bottle development server is still running or re-run it with
the <code>python app.py</code> command in a shell where your virtualenv is still
activated.</p>
<p>Bring up the application in a browser, this time test out the phone calling
capabilities. Go to "localhost:8000/dial-phone/my-phone-number", where
"my-phone-number" is a number in the "+12025551234" format. For example,
here is what happens when I dialed +12023351278:</p>
<p><img src="/source/static/img/160830-phone-calls-bottle/phone-call-placed.png" width="100%" class="technical-diagram img-rounded" alt="Dialing an outbound phone call with Bottle."></p>
<p>And here is the inbound phone call!</p>
<p><img src="/source/static/img/160830-phone-calls-bottle/inbound-call.png" width="100%" class="technical-diagram img-rounded" alt="Receiving an incoming phone call on the iPhone."></p>
<p>When we pick up the phone call we also see the <code>/twiml</code> route get called via
Ngrok.</p>
<p><img src="/source/static/img/160830-phone-calls-bottle/ngrok-twiml.png" width="100%" class="technical-diagram img-rounded" alt="/twiml route being called via Ngrok."></p>
<p>With just two routes in our Bottle app and Twilio we were able to make
outbound phone calls. Not bad!</p>
<h2>What's next?</h2>
<p>Sweet, we can now dial outbound phone calls to <em>any</em> phone number from
our Bottle web application. Next you may want to try one of these tutorials
to add even more features to your app:</p>
<ul>
<li>Upgrade your <a href="/blog/reply-sms-text-messages-python-bottle.html">Bottle app to also send and respond to text messages</a></li>
<li>Create a <a href="https://www.twilio.com/blog/2016/05/add-phone-calling-slack-python.html">phone-calling Slack bot</a></li>
<li>Implement <a href="https://www.twilio.com/docs/tutorials/walkthrough/call-tracking/python/django">call tracking</a>
for both inbound and outbound phone calls made through your app</li>
</ul>
<p>Questions? Contact me via Twitter
<a href="https://twitter.com/fullstackpython">@fullstackpython</a>
or <a href="https://twitter.com/mattmakai">@mattmakai</a>. I'm also on GitHub as
<a href="https://github.com/mattmakai">mattmakai</a>.</p>
<p>Something wrong with this post? Fork
<a href="https://github.com/mattmakai/fullstackpython.com/blob/gh-pages/source/content/posts/160830-phone-calls-bottle.markdown">this page's source on GitHub</a>.</p></summary></entry><entry><title>Python for Entrepreneurs</title><link href="https://www.fullstackpython.com/python-entrepreneurs.html" rel="alternate"></link><updated>2016-08-22T00:00:00-04:00</updated><author><name>Matt Makai</name></author><id>tag:www.fullstackpython.com,2016-07-30:python-entrepreneurs.html</id><summary type="html"><p><a href="https://www.kickstarter.com/projects/mikeckennedy/python-for-entrepreneurs-video-course">Python for Entrepreneurs</a>
is a new video course by the creators of
<a href="https://talkpython.fm/">Talk Python to Me</a> and
<a href="https://fullstackpython.com/">Full Stack Python</a>.</p>
<p>We are creating this course and running a Kickstarter for it based on
feedback that it's still too damn difficult to turn basic Python programming
knowledge into a business to generate income as a side or full time project.
Both Michael and I have been able to make that happen for ourselves and we
want to share every difficult lesson we've learned through this course.</p>
<p>The Python for Entrepreneurs videos and content will dive into building
and deploying a real-world web application, marketing it to prospective
customers, handling search engine optimization, making money through credit
card payments, getting help from part-time contractors for niche tasks and
scaling up to meet traffic demands.</p>
<p>If this course hits the mark for what you want to do with Python,
<a href="https://www.kickstarter.com/projects/mikeckennedy/python-for-entrepreneurs-video-course">check out the Kickstarter</a> - we've
set up steep discounts for early backers.</p>
<p><em>Update</em>: The Kickstarter is now closed - Michael and I are hard at work
on the course content. Thank you to everyone who supported us as a backer!</p>
<p>If you have any questions, please reach out to
<a href="https://twitter.com/mkennedy">Michael Kennedy</a>
or me, <a href="https://twitter.com/mattmakai">Matt Makai</a>.</p></summary></entry><entry><title>Setting Up Python 3, Django & Gunicorn on Linux Mint 17.3</title><link href="https://www.fullstackpython.com/python-3-django-gunicorn-linux-mint-17.html" rel="alternate"></link><updated>2016-07-22T00:00:00-04:00</updated><author><name>Matt Makai</name></author><id>tag:www.fullstackpython.com,2016-06-26:python-3-django-gunicorn-linux-mint-17.html</id><summary type="html"><p>Linux Mint 17.3 "Rosa" is December 2015 release of the polished and
widely-used Linux distribution. This Mint release includes both Python 2.7
and 3.4 by default, but in this tutorial we will download and install the
latest Python 3.5.1 version to run our Django application. </p>
<p>If you want to use a different Linux distribution such as
<a href="/ubuntu.html">Ubuntu</a> instead of Mint, check out
<a href="/blog/python-3-django-gunicorn-ubuntu-1604-xenial-xerus.html">the tutorial for Ubuntu 16.04 "Xenial Xerus"</a>. If Mint is your desired
<a href="/development-environments.html">development environment</a> though, let's
get started!</p>
<h2>Tools We Need</h2>
<p>Our setup will use several system packages and code libraries to get
up and running. Do not worry about installing these dependencies just yet,
we will get to them as we progress through the tutorial. The tools and
their current versions as of June 2016 are:</p>
<ul>
<li><a href="http://blog.linuxmint.com/?p=2947">Linux Mint 17.3 "Rosa"</a> with the
default Cinnamon desktop</li>
<li><a href="/why-use-python.html">Python</a> version
<a href="https://www.python.org/downloads/release/python-351/">3.5.1</a></li>
<li><a href="/django.html">Django</a> web framework version
<a href="https://docs.djangoproject.com/en/1.9/releases/1.9/">1.9.7</a></li>
<li><a href="/green-unicorn-gunicorn.html">Green Unicorn (Gunicorn)</a> version
<a href="http://docs.gunicorn.org/en/stable/news.html">19.6</a></li>
</ul>
<p>If you are on Mac OS X or Windows, my recommendation is to use
virtualization software such as
<a href="https://www.parallels.com/products/desktop/">Parallels</a> or
<a href="https://www.virtualbox.org/wiki/Downloads">VirtualBox</a> with the
<a href="https://www.linuxmint.com/download.php">Linux Mint Cinnamon desktop .iso</a>.</p>
<p>We should see a desktop screen like this one when we boot up the operating
system for the first time.</p>
<p><img src="/source/static/img/160626-mint-django-gunicorn/mint-desktop.jpg" width="100%" class="technical-diagram img-rounded" alt="Linux Mint default desktop"></p>
<p>Open up terminal to proceed with the configuration.</p>
<h2>System Packages</h2>
<p>We can see the Python version Linux Mint comes with, as well as where its
executable is stored.</p>
<div class="highlight"><pre>python3 --version
which python3
</pre></div>
<p>The <em>output</em> of those two commands should be (these are not commands to run):</p>
<div class="highlight"><pre>Python 3.4.3
/usr/bin/python3
</pre></div>
<p><img src="/source/static/img/160626-mint-django-gunicorn/which-python.png" width="100%" class="technical-diagram img-rounded" alt="Output of 'python --version' and 'which python3' commands."></p>
<p>We really want to use the latest Python release instead of the default 3.4
when starting a new Python project, so let's download and install 3.5.1 now.</p>
<p>Run these commands in the terminal to download Python 3.5.1 source code:</p>
<div class="highlight"><pre>cd ~/Downloads
wget https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz
</pre></div>
<p><img src="/source/static/img/160626-mint-django-gunicorn/download-python.png" width="100%" class="technical-diagram img-rounded" alt="wget Python source code output."></p>
<p>Extract the Python source code:</p>
<div class="highlight"><pre>tar -xvf Python-3.5.1.tgz
</pre></div>
<p>Linux Mint is not configured by default to build the Python source code. We
need to update our system package lists and install several packages to
make building the Python source code possible. If you have a password on
your user account, enter it when prompted to allow the installation to
proceed.</p>
<div class="highlight"><pre>sudo apt update
sudo apt install build-essential checkinstall
sudo apt install libreadline-gplv2-dev libncursesw5-dev libssl-dev
sudo apt install libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev
sudo apt install python3-dev
</pre></div>
<p>Once the packages are installed, we can configure and install Python from
source.</p>
<div class="highlight"><pre>cd Python-3.5.1
./configure
sudo make install
</pre></div>
<p>Test that the installation worked properly by starting up the Python REPL:</p>
<div class="highlight"><pre>python3.5
</pre></div>
<p>If the REPL starts up properly with Python 3.5.1 in the output then we're
good to go.</p>
<p><img src="/source/static/img/160626-mint-django-gunicorn/python351-output.png" width="100%" class="technical-diagram img-rounded" alt="wget Python source code output."></p>
<p>The basic system packages we need are now installed so we can proceed to
our Python-specific dependencies.</p>
<h2>Virtual environment and pip</h2>
<p>Python 3.5 comes with the virtual environment and pip applications so we
can use them to handle our
<a href="/application-dependencies.html">application dependencies</a>.</p>
<p>Create a directory to store virtual environments then create a virtualenv
for our Django project.</p>
<div class="highlight"><pre># the tilde &quot;~&quot; specifies the user&#39;s home directory, like /home/matt
cd ~
mkdir venvs
# specify the system python3 installation
python3.5 -m venv djangoproj
</pre></div>
<p>Activate the virtualenv.</p>
<div class="highlight"><pre>source ~/venvs/djangoproj/bin/activate
</pre></div>
<p>Our virtual environment is properly activated when we see <code>(djangoproj)</code>
prepended to our prompt. </p>
<p><img src="/source/static/img/160626-mint-django-gunicorn/venv-activated.png" width="100%" class="technical-diagram img-rounded" alt="Output from the virtualenv environment activation."></p>
<p>Our virtualenv with Python 3.5.1 is activated so we can install whatever
dependencies we want, such as Django and Gunicorn. Our default <code>python</code>
command is also set to use the Python 3.5.1 installation instead of the
Python 2.7 version that comes with Linux Mint.</p>
<h2>Django and Gunicorn</h2>
<p>Now we can install Django and Green Unicorn into our virtual environment.</p>
<div class="highlight"><pre>pip install django==1.9.7 gunicorn==19.6
</pre></div>
<p>If there are no errors in the pip output then that is a good sign we can
proceed.</p>
<p><img src="/source/static/img/160626-mint-django-gunicorn/good-sign.png" width="100%" class="technical-diagram img-rounded" alt="Django and Gunicorn properly install via the pip command."></p>
<p>Create a new Django project named <code>djangoproj</code>, or whatever you want to name
your project. Change into the directory for the new project.</p>
<div class="highlight"><pre>cd ~
django-admin startproject djangoproj
cd djangoproj
</pre></div>
<p>We can run Django using the development server with the
<code>python manage.py runserver</code> command. However, start Django up with
Gunicorn instead.</p>
<div class="highlight"><pre>gunicorn djangoproj.wsgi
</pre></div>
<p><img src="/source/static/img/160626-mint-django-gunicorn/gunicorn-run.png" width="100%" class="technical-diagram img-rounded" alt="Result of running gunicorn djangoproj.wsgi on the command line."></p>
<p>Awesome, we can bring up our shell project in the web browser at
the <a href="http://localhost:8000">http://localhost:8000</a> or
<a href="http://127.0.0.1:8000">http://127.0.0.1:8000</a> address.</p>
<p><img src="/source/static/img/160626-mint-django-gunicorn/it-works.png" width="100%" class="technical-diagram img-rounded" alt="Django project running in the Firefox web browser."></p>
<p>Now you're ready for Django development!</p>
<h2>Ready for Development</h2>
<p>Those are the first few steps for beginning development with
<a href="/django.html">Django</a> and <a href="/green-unicorn-gunicorn.html">Gunicorn</a> on
Linux Mint 17.3 "Rosa". If you need an even more in-depth walkthrough for
deploying your Python web application to a production environment, check
out the
<a href="http://www.deploypython.com/">Full Stack Python Guide to Deployments book</a>.</p>
<p>To figure out what to do next for your Python project, read the topics
found on the <a href="/table-of-contents.html">table of contents</a> page.</p>
<p>Questions? Contact me via Twitter
<a href="https://twitter.com/fullstackpython">@fullstackpython</a>
or <a href="https://twitter.com/mattmakai">@mattmakai</a>. I'm also on GitHub with
the username <a href="https://github.com/mattmakai">mattmakai</a>.</p>
<p>See something wrong in this post? Fork
<a href="https://github.com/mattmakai/fullstackpython.com/blob/gh-pages/source/content/posts/160626-django-gunicorn-mint-linux-17.markdown">this page's source on GitHub</a>
and submit a pull request.</p></summary></entry><entry><title>Configuring Python 3, Pyramid and Gunicorn on Ubuntu 16.04</title><link href="https://www.fullstackpython.com/python-3-pyramid-gunicorn-ubuntu-1604-xenial-xerus.html" rel="alternate"></link><updated>2016-08-10T00:00:00-04:00</updated><author><name>Matt Makai</name></author><id>tag:www.fullstackpython.com,2016-06-19:python-3-pyramid-gunicorn-ubuntu-1604-xenial-xerus.html</id><summary type="html"><p><a href="/ubuntu.html">Canonical's Ubuntu 16.04 Long Term Support (LTS)</a> Linux
<a href="/operating-systems.html">operating system</a>, also known as "Xenial Xerus",
was released in April 2016. It is the first Ubuntu release to include
<a href="/python-2-or-3.html">Python 3</a> instead of Python 2 as its default Python
installation.</p>
<p>The <a href="/pyramid.html">Pyramid</a> web framework has long supported Python 3.
With just a few short steps we can start a new <a href="/pyramid.html">Pyramid</a>
project and run it with
<a href="/green-unicorn-gunicorn.html">Green Unicorn (Gunicorn)</a> on Ubuntu 16.04.</p>
<h2>Required Tools</h2>
<p>Our project requires Ubuntu 16.04 plus several code libraries. You do not
need to install these tools yet - we will get to them in turn as the
walkthrough progresses. Our requirements and their current versions are:</p>
<ul>
<li><a href="http://releases.ubuntu.com/16.04/">Ubuntu 16.04 LTS (Xenial Xerus)</a></li>
<li><a href="/why-use-python.html">Python version 3.5</a> (default in Ubuntu 16.04)</li>
<li><a href="/pyramid.html">Pyramid web framework</a> version
<a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/">1.7</a></li>
<li><a href="/green-unicorn-gunicorn.html">Gunicorn</a> version
<a href="http://docs.gunicorn.org/en/stable/news.html">19.6</a></li>
<li><a href="http://docs.pylonsproject.org/projects/waitress/en/latest/">Waitress</a>
version 0.9.0</li>
</ul>
<p>If you are developing on Mac OS X or Windows, you can use
virtualization software such
as <a href="https://www.parallels.com/products/desktop/">Parallels</a> or
<a href="https://www.virtualbox.org/wiki/Downloads">VirtualBox</a> with the
<a href="http://releases.ubuntu.com/16.04/">Ubuntu .iso file</a>. Either the amd64 or
i386 version of 16.04 is fine. While creating this I used the amd64 version. </p>
<p>A desktop screen like this one appears when you boot up Ubuntu.</p>
<p><img src="/source/static/img/160619-ubuntu-pyramid-gunicorn/ubuntu-desktop.jpg" width="100%" class="technical-diagram img-rounded"></p>
<p>Open a new terminal window so we can be ready to install required system
packages.</p>
<h2>Install System Packages</h2>
<p>The precise Python version can be shown using the <code>python</code> command with the
<code>--version</code> argument.</p>
<div class="highlight"><pre>python3 --version
</pre></div>
<p>We can also view where the <code>python3</code> program is installed on Ubuntu using the
<code>which</code> command.</p>
<div class="highlight"><pre>which python3
</pre></div>
<p><img src="/source/static/img/160619-ubuntu-pyramid-gunicorn/which-python.png" width="100%" class="technical-diagram img-rounded"></p>
<p>Ubuntu requires a few system packages before we can properly install Pyramid
and Gunicorn. When we run the <code>apt</code> command to install system packages we
will be prompted for the superuser password. Restricted system access is
necessary to modify files within the system folders.</p>
<div class="highlight"><pre>sudo apt-get install python3-dev
</pre></div>
<p><img src="/source/static/img/160619-ubuntu-pyramid-gunicorn/install-packages.png" width="100%" class="technical-diagram img-rounded"></p>
<p>Press <code>y</code> then return to let the system package installation run.</p>
<p><img src="/source/static/img/160619-ubuntu-pyramid-gunicorn/packages-installed.png" width="100%" class="technical-diagram img-rounded"></p>
<p>The required system packages are installed. We can now install the
Python-specific dependencies.</p>
<h2>Set up a virtual environment</h2>
<p>Create a directory for the virtual environments. Then create a new virtual environment.</p>
<div class="highlight"><pre># the tilde &quot;~&quot; specifies the user&#39;s home directory, like /home/matt
cd ~
mkdir venvs
# specify the system python3 installation
/usr/bin/python3 -m venv venvs/pyramidproj
</pre></div>
<p>Activate the virtual environment.</p>
<div class="highlight"><pre>source ~/venvs/pyramidproj/bin/activate
</pre></div>
<p>Our prompt will change after we properly activate the virtual environment to
something like <code>(pyramidproj) matt@ubuntu:~$</code>.</p>
<p><img src="/source/static/img/160619-ubuntu-pyramid-gunicorn/venv-activated.png" width="100%" class="technical-diagram img-rounded"></p>
<p>Our virtual environment is activated with Python 3.</p>
<p>We should update pip and venv to the latest versions in our virtual environment.</p>
<div class="highlight"><pre>pip install --upgrade pip setuptools
</pre></div>
<p>We can install whatever dependencies we want, in our case Pyramid and Gunicorn. </p>
<h2>Install Python Packages</h2>
<p>We can install Pyramid, Gunicorn and Waitress into our virtual environment using
the <code>pip</code> command.</p>
<div class="highlight"><pre>pip install pip install &quot;pyramid==1.7&quot; gunicorn waitress
</pre></div>
<p>No errors like we see in the following screenshot is a good sign.</p>
<p><img src="/source/static/img/160619-ubuntu-pyramid-gunicorn/good-sign.png" width="100%" class="technical-diagram img-rounded"></p>
<p>Pyramid comes with a project starter template creation tool named <code>pcreate</code>.
Run <code>pcreate</code> to generate the boilerplate for a new Pyramid project named
"pyramidproj".</p>
<div class="highlight"><pre>pcreate -s starter pyramidproj
</pre></div>
<p>Use the <code>cd</code> (change directory) command to move into the new folder.</p>
<div class="highlight"><pre>cd ~/pyramidproj
</pre></div>
<p>A slew of new files have been created within the "pyramidproj" directory.
These are the basic files you can customize for the web application you want
to build. A good resource for understanding and modifying these files is
to follow the
<a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/quick_tutorial/index.html">quick tutorial for Pyramid</a>.</p>
<p>For now, we just want to use Gunicorn to run our starter pyramidproj app.
Install pyramidproj into your virtual environment using the <code>python</code> command on
<code>setup.py</code>.</p>
<div class="highlight"><pre>python setup.py develop
</pre></div>
<p>Now we can run our app with Gunicorn. Pyramid is a
<a href="http://docs.pylonsproject.org/projects/pyramid/en/latest/api/paster.html">paste</a>-compatible
framework, so we use the <code>--paste</code> argument to run the WSGI server with
the "development.ini" configuration file. In addition, the <code>-b</code> argument
tells Gunicorn which port number to bind on when the server starts.</p>
<div class="highlight"><pre>gunicorn --paste development.ini -b :8080
</pre></div>
<p><img src="/source/static/img/160619-ubuntu-pyramid-gunicorn/gunicorn-run.png" width="100%" class="technical-diagram img-rounded"></p>
<p>Cool, we can bring up our starter Pyramid project up in the web browser at
the <code>localhost:8000</code> or <code>127.0.0.1:8000</code> address.</p>
<p><img src="/source/static/img/160619-ubuntu-pyramid-gunicorn/it-works.png" width="100%" class="technical-diagram img-rounded"></p>
<p>Time to develop a full-fledged web application with <a href="/pyramid.html">Pyramid</a>!</p>
<h2>Ready to Develop with Pyramid</h2>
<p>Now you have a simple setup to develop Pyramid web apps using Gunicorn as
the <a href="/wsgi-servers.html">WSGI server</a> on Ubuntu 16.04. If you need a
full step-by-step tutorial to deploy your Python web application to a
production environment, check out the
<a href="http://www.deploypython.com/">Full Stack Python Guide to Deployments book</a>.</p>
<p>To decide what to do next with your Python project, check out the
<a href="/table-of-contents.html">Full Stack Python table of contents</a> page.</p>
<p>See something wrong in this post? Fork
<a href="https://github.com/mattmakai/fullstackpython.com/blob/gh-pages/source/content/posts/160619-pyramid-gunicorn-ubuntu-1604.markdown">this page's source on GitHub</a>
and submit a pull request.</p></summary></entry><entry><title>Replying to SMS Text Messages with Python and Bottle</title><link href="https://www.fullstackpython.com/reply-sms-text-messages-python-bottle.html" rel="alternate"></link><updated>2016-08-10T00:00:00-04:00</updated><author><name>Matt Makai</name></author><id>tag:www.fullstackpython.com,2016-06-05:reply-sms-text-messages-python-bottle.html</id><summary type="html"><p>Python applications can
<a href="/blog/send-sms-text-messages-python.html">easily send SMS</a>
by using a <a href="/application-programming-interfaces.html">web API</a>.
Web apps built with the <a href="/bottle.html">Bottle</a> framework can also reply
to incoming text messages by handling inbound HTTP POST webhooks. In
this post we'll quickly walk through how to set up a Bottle web app to
handle SMS data in the form of HTTP POST requests.</p>
<h2>Tools We'll Need</h2>
<p>This tutorial works with either <a href="/python-2-or-3.html">Python 2 or 3</a>,
although Python 3 is recommended by the community for new applications.
Install one of those two Python versions on your system to use for this
walkthrough. We also need:</p>
<ul>
<li><a href="https://pip.pypa.io/en/stable/">pip</a> and
<a href="https://virtualenv.pypa.io/en/latest/">virtualenv</a> to handle
<a href="/application-dependencies.html">application dependencies</a></li>
<li><a href="/bottle.html">Bottle</a> web framework</li>
<li><a href="https://ngrok.com/">Ngrok</a> for localhost tunneling to our Bottle
application while it's running on our local development environment</li>
<li>Free <a href="https://www.twilio.com/try-twilio">Twilio account</a> to use their
<a href="https://www.twilio.com/docs/api/rest/sending-messages">SMS web API</a></li>
<li>Open source
<a href="https://pypi.python.org/pypi/twilio">Twilio Python helper library</a></li>
</ul>
<p>Check out the guide on
<a href="/blog/python-3-bottle-gunicorn-ubuntu-1604-xenial-xerus.html">how to set up Python 3, Bottle and Gunicorn on Ubuntu 16.04 LTS</a>
if you need help getting your
<a href="/development-environments.html">development environment</a>
configured.</p>
<h2>Application Dependency Installation</h2>
<p>Our application will use a helper code library to reply to inbound SMS.
Bottle and the helper library are installable from
<a href="https://pypi.python.org/pypi">PyPI</a> into a virtualenv. Open your terminal
and use the <code>virtualenv</code> command to create a new virtualenv:</p>
<div class="highlight"><pre>virtualenv replysms
</pre></div>
<p>Invoke the virtualenv's <code>activate</code> script, which makes it the "active"
Python installation. Note that you need to do this in every terminal window
that you want this virtualenv to be used.</p>
<div class="highlight"><pre>source replysms/bin/activate
</pre></div>
<p>The command prompt will change after activating the virtualenv:</p>
<p><img src="/source/static/img/160605-reply-sms-python-bottle/activate-virtualenv.png" width="100%" class="technical-diagram img-rounded"></p>
<p>Use the <code>pip</code> command to install the <a href="/bottle.html">Bottle</a> and
<a href="https://www.twilio.com/docs/libraries/python">Twilio Python</a> packages
into your virtualenv.</p>
<div class="highlight"><pre>pip install bottle twilio
</pre></div>
<p>We have installed the required dependencies so now Python code that is run
with the virtualenv activated will be able to use those packages. It's time
to build our Bottle web app and reply to incoming text messages.</p>
<h2>Coding Our Bottle App</h2>
<p>The Bottle web app will have two routes. One route will allow us to test
that the app is running. The other route will handle and respond to incoming
HTTP POST requests from Twilio. Create a new file named <code>app.py</code> in your
in the directory where you want to store this Python project.</p>
<p>Write the following code in the new <code>app.py</code> file. There is also
<a href="https://gist.github.com/mattmakai/6ec3b46e40a1020a3ea9c772c601199a">a GitHub Gist</a>
with the code that you can copy and paste.</p>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="p">(</span><span class="n">post</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">response</span><span class="p">,</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span><span class="p">,</span> <span class="p">)</span>
<span class="kn">from</span> <span class="nn">twilio</span> <span class="kn">import</span> <span class="n">twiml</span>
<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">check_app</span><span class="p">():</span>
<span class="c"># returns a simple string stating the app is working</span>
<span class="k">return</span> <span class="s">&quot;It works!&quot;</span>
<span class="nd">@post</span><span class="p">(</span><span class="s">&#39;/twilio&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">inbound_sms</span><span class="p">():</span>
<span class="n">twiml_response</span> <span class="o">=</span> <span class="n">twiml</span><span class="o">.</span><span class="n">Response</span><span class="p">()</span>
<span class="c"># grab message from the request. could also get the &quot;To&quot; and </span>
<span class="c"># &quot;From&quot; phone numbers as well from parameters with those names</span>
<span class="n">inbound_message</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">forms</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&quot;Body&quot;</span><span class="p">)</span>
<span class="c"># we can now use the incoming message text in our Python application</span>
<span class="k">if</span> <span class="n">inbound_message</span> <span class="o">==</span> <span class="s">&quot;Hello&quot;</span><span class="p">:</span>
<span class="n">twiml_response</span><span class="o">.</span><span class="n">message</span><span class="p">(</span><span class="s">&quot;Hello from Bottle right back at you!&quot;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">twiml_response</span><span class="o">.</span><span class="n">message</span><span class="p">(</span><span class="s">&quot;Hi! Not quite sure what you meant, but okay.&quot;</span><span class="p">)</span>
<span class="c"># we return back the mimetype because Twilio needs an XML response</span>
<span class="n">response</span><span class="o">.</span><span class="n">content_type</span> <span class="o">=</span> <span class="s">&quot;application/xml&quot;</span>
<span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">twiml_response</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
<span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">&#39;127.0.0.1&#39;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">5000</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">reloader</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
</pre></div>
<p>The lines starting with <code>#</code> are comments that give explanations for what
the code lines below them are doing. Bottle web apps define URL routes with
the <code>@route</code> and <code>@post</code> decorators, depending on the type of HTTP request
the route should handle. </p>
<p>Make sure your virtualenv is still active so that the application can use
the Bottle and Twilio code libraries we installed earlier. Give the
application a try by running it with <code>python app.py</code>. </p>
<p>Open a web browser and go to localhost:5000 (or 127.0.0.1:5000). We should
see "It works!" on the screen.</p>
<p><img src="/source/static/img/160605-reply-sms-python-bottle/bottle-app-local.jpg" width="100%" class="technical-diagram img-rounded" alt="Bottle application running locally on Ubuntu."></p>
<p>However, there is an issue with our web app running on our local development
environment. Twilio cannot send a the HTTP POST request to the web app
server unless a localhost tunnel is created.</p>
<h2>Ngrok Localhost Tunneling</h2>
<p><a href="https://ngrok.com">Ngrok</a> is a localhost tunneling tool that bridges
your local development environment to an external URL.
<a href="https://ngrok.com/download">Download and install</a> the Ngrok version that's
appropriate for your operating system.</p>
<p>We can run Ngrok locally and expose our Bottle app that is running on
port 5000. Run this command within the directory where the Ngrok executable is
located.</p>
<div class="highlight"><pre>./ngrok http 5000
</pre></div>
<p><img src="/source/static/img/160605-reply-sms-python-bottle/start-ngrok.jpg" width="100%" class="technical-diagram img-rounded" alt="Ngrok started and running to serve as a localhost tunnel."></p>
<p>Cool, now we can use the Forwarding URL so Twilio can send POST requests
to our application when there is an inbound SMS. Replace the URL in the
text box with your own Forwarding URL, like I did in this screenshot.</p>
<p><img src="/source/static/img/160605-reply-sms-python-bottle/access-ngrok.jpg" width="100%" class="technical-diagram img-rounded" alt="Paste the ngrok Forwarding URL into the Twilio webhook configuration text box."></p>
<p>Now we just need a Twilio phone number that will send POST request to our
application when there is an inbound SMS.</p>
<h2>Obtain a Phone Number</h2>
<p>Our Bottle web app's route can respond to incoming POST requests but we
need to use Twilio to have a phone number that will convert the inbound SMS
data into the POST request. In your web browser go to the
<a href="https://www.twilio.com/try-twilio">Twilio website and sign up for a free account</a>.
You can also sign into your existing Twilio account if you already have one.</p>
<p><img src="/source/static/img/160605-reply-sms-python-bottle/try-twilio.png" width="100%" class="technical-diagram img-rounded" alt="Twilio sign up screen."></p>
<p>The Twilio trial account allows you to send and receive text messages to
your own validated phone number. To send and reply to SMS to and from any
phone number then you need to upgrade your account. Trial accounts are
great for initial development before your application goes live.</p>
<p>When you sign up, you receive a free Twilio phone number. We can
configure that phone number to forward the SMS information to our web
application by setting up the response webhook.</p>
<p>Go to the
<a href="https://www.twilio.com/console/phone-numbers">manage phone numbers screen</a>
and click on the phone number you want to configure for replying to
text messages.</p>
<p>Scroll down and look for the "Messaging" header. Change the
"A Message Comes in" text box to input the ngrok Forwarding URL plus
the "/twilio" route, as shown in the screenshot below.</p>
<p><img src="/source/static/img/160605-reply-sms-python-bottle/webhook-ngrok.jpg" width="100%" class="technical-diagram img-rounded" alt="Paste the ngrok Forwarding URL into the Twilio webhook configuration text box."></p>
<p>Click the "Save" button so that our changes take effect.</p>
<p>Our application is ready to go - time to give our phone number a try!
Send "Hello" or whatever text you want to your phone number. Here is what
the result looks like on my iPhone.</p>
<p><img src="/source/static/img/160605-reply-sms-python-bottle/bottle-success.png" width="100%" class="technical-diagram img-rounded" alt="Example screenshot of what SMS replies look like on the iPhone."></p>
<p>The concise Bottle web app is a good start to build more complicated
programs such as
<a href="https://www.twilio.com/blog/2014/11/choose-your-own-adventure-presentations-with-reveal-js-python-and-websockets.html">Choose Your Own Adventure Presentations</a>
or
<a href="https://www.twilio.com/blog/2016/05/build-sms-slack-bot-python.html">SMS Slack bots</a>.</p>
<h2>What's next?</h2>
<p>Awesome, our Bottle application now replies to inbound SMS text
messages! </p>
<p>Questions? Contact me via Twitter
<a href="https://twitter.com/fullstackpython">@fullstackpython</a>
or <a href="https://twitter.com/mattmakai">@mattmakai</a>. I'm also on GitHub with
the username <a href="https://github.com/mattmakai">mattmakai</a>.</p>
<p>Something wrong with this post? Fork
<a href="https://github.com/mattmakai/fullstackpython.com/blob/gh-pages/source/content/posts/160605-reply-sms-python-bottle.markdown">this page's source on GitHub</a>.</p></summary></entry><entry><title>How to Build Your First Slack Bot with Python</title><link href="https://www.fullstackpython.com/build-first-slack-bot-python.html" rel="alternate"></link><updated>2016-10-27T00:00:00-04:00</updated><author><name>Matt Makai</name></author><id>tag:www.fullstackpython.com,2016-06-04:build-first-slack-bot-python.html</id><summary type="html"><p><a href="/bots.html">Bots</a> are a useful way to interact with chat services such as
<a href="https://slack.com/">Slack</a>. If you have never built a bot before, this
post provides an easy starter tutorial for combining the
<a href="https://api.slack.com/">Slack API</a> with Python to create your first bot.</p>
<p>We will walk through setting up your development environment, obtaining a
Slack API bot token and coding our simple bot in Python.</p>
<h2>Tools We Need</h2>
<p>Our bot, which we will name "StarterBot", requires Python and the Slack API.
To run our Python code we need:</p>
<ul>
<li>Either <a href="/python-2-or-3.html">Python 2 or 3</a></li>
<li><a href="https://pip.pypa.io/en/stable/">pip</a> and
<a href="https://virtualenv.pypa.io/en/stable/">virtualenv</a> to handle Python
<a href="/application-dependencies.html">application dependencies</a></li>
<li><a href="https://slack.com/">Free Slack account</a> with a team on which you have
API access or sign up for the
<a href="http://dev4slack.xoxco.com/">Slack Developer Hangout team</a></li>
<li>Official Python
<a href="https://github.com/slackhq/python-slackclient">slackclient</a> code
library built by the Slack team</li>
<li><a href="https://api.slack.com/tokens">Slack API testing token</a></li>
</ul>
<p>It is also useful to have the <a href="https://api.slack.com/">Slack API docs</a> handy
while you're building this tutorial.</p>
<p>All the code for this tutorial is available open source under the MIT license
in the <a href="https://github.com/mattmakai/slack-starterbot">slack-starterbot</a> public
repository.</p>
<h2>Establishing Our Environment</h2>
<p>We now know what tools we need for our project so let's get our development
environment set up. Go to the terminal (or Command Prompt on Windows) and
change into the directory where you want to store this project. Within
that directory, create a new virtualenv to isolate our application
dependencies from other Python projects.</p>
<div class="highlight"><pre>virtualenv starterbot
</pre></div>
<p>Activate the virtualenv:</p>
<div class="highlight"><pre>source starterbot/bin/activate
</pre></div>
<p>Your prompt should now look like the one in this screenshot.</p>
<p><img src="/source/static/img/160604-simple-python-slack-bot/virtualenv-activate.png" width="100%" class="technical-diagram img-rounded" alt="Command prompt with starterbot's virtualenv activated."></p>
<p>The official slackclient API helper library built by Slack can send and
receive messages from a Slack channel. Install the slackclient library with
the <code>pip</code> command:</p>
<div class="highlight"><pre>pip install slackclient
</pre></div>
<p>When <code>pip</code> is finished you should see output like this and you'll be
back at the prompt.</p>
<p><img src="/source/static/img/160604-simple-python-slack-bot/pip-install-slackclient.png" width="100%" class="technical-diagram img-rounded" alt="Output from using the pip install slackclient command with a virtualenv activated."></p>
<p>We also need to obtain an access token for our Slack team so our bot can
use it to connect to the Slack API.</p>
<h2>Slack Real Time Messaging (RTM) API</h2>
<p>Slack grants programmatic access to their messaging channels via a