forked from mattmakai/fullstackpython.com
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfeed
2025 lines (1771 loc) · 168 KB
/
feed
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"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Full Stack Python</title><link>https://www.fullstackpython.com/</link><description></description><atom:link href="https://www.fullstackpython.com/feed" rel="self"></atom:link><lastBuildDate>Sat, 06 Aug 2016 00:00:00 -0400</lastBuildDate><item><title>Python for Entrepreneurs</title><link>https://www.fullstackpython.com/python-entrepreneurs.html</link><description><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>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></description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Makai</dc:creator><pubDate>Sat, 06 Aug 2016 00:00:00 -0400</pubDate><guid>tag:www.fullstackpython.com,2016-07-30:python-entrepreneurs.html</guid></item><item><title>Setting Up Python 3, Django & Gunicorn on Linux Mint 17.3</title><link>https://www.fullstackpython.com/python-3-django-gunicorn-linux-mint-17.html</link><description><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/makaimc">makaimc</a>.</p>
<p>See something wrong in this post? Fork
<a href="https://github.com/makaimc/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></description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Makai</dc:creator><pubDate>Fri, 22 Jul 2016 00:00:00 -0400</pubDate><guid>tag:www.fullstackpython.com,2016-06-26:python-3-django-gunicorn-linux-mint-17.html</guid></item><item><title>Configuring Python 3, Pyramid and Gunicorn on Ubuntu 16.04</title><link>https://www.fullstackpython.com/python-3-pyramid-gunicorn-ubuntu-1604-xenial-xerus.html</link><description><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/makaimc/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></description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Makai</dc:creator><pubDate>Tue, 21 Jun 2016 00:00:00 -0400</pubDate><guid>tag:www.fullstackpython.com,2016-06-19:python-3-pyramid-gunicorn-ubuntu-1604-xenial-xerus.html</guid></item><item><title>Replying to SMS Text Messages with Python and Bottle</title><link>https://www.fullstackpython.com/reply-sms-text-messages-python-bottle.html</link><description><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/makaimc/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/makaimc">makaimc</a>.</p>
<p>Something wrong with this post? Fork
<a href="https://github.com/makaimc/fullstackpython.com/blob/gh-pages/source/content/posts/160605-reply-sms-python-bottle.markdown">this page's source on GitHub</a>.</p></description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Makai</dc:creator><pubDate>Sun, 05 Jun 2016 00:00:00 -0400</pubDate><guid>tag:www.fullstackpython.com,2016-06-05:reply-sms-text-messages-python-bottle.html</guid></item><item><title>How to Build Your First Slack Bot with Python</title><link>https://www.fullstackpython.com/build-first-slack-bot-python.html</link><description><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/makaimc/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
<a href="/application-programming-interfaces.html">web API</a>. Go to the
<a href="https://api.slack.com/">Slack web API page</a> and sign up to create your own
Slack team. You can also sign into an existing account where you have
administrative privileges.</p>
<p><img src="/source/static/img/160604-simple-python-slack-bot/sign-in-slack.png" width="100%" class="technical-diagram img-rounded" alt="Use the sign in button on the top right corner of the Slack API page."></p>
<p>After you have signed in go to the
<a href="https://api.slack.com/bot-users">Bot Users page</a>.</p>
<p><img src="/source/static/img/160604-simple-python-slack-bot/custom-bot-users.png" width="100%" class="technical-diagram img-rounded" alt="Custom bot users webpage."></p>
<p>Name your bot "starterbot" then click the “Add bot integration” button.</p>
<p><img src="/source/static/img/160604-simple-python-slack-bot/starterbot.jpg" width="100%" class="technical-diagram img-rounded" alt="Add a bot integration named starterbot."></p>
<p>The page will reload and you will see a newly-generated access token. You
can also change the logo to a custom design. For example, I gave this bot
the Full Stack Python logo.</p>
<p><img src="/source/static/img/160604-simple-python-slack-bot/slack-token.png" width="100%" class="technical-diagram img-rounded" alt="Copy and paste the access token for your new Slack bot."></p>
<p>Click the "Save Integration" button at the bottom of the page. Your bot is
now ready to connect to Slack's API.</p>
<p>A common practice for Python developers is to export secret tokens as
environment variables. Export the Slack token with the name
<code>SLACK_BOT_TOKEN</code>:</p>
<div class="highlight"><pre>export SLACK_BOT_TOKEN=&#39;your slack token pasted here&#39;
</pre></div>
<p>Nice, now we are authorized to use the Slack API as a bot.</p>
<p>There is one more piece of information we need to build our bot: our bot's
ID. Next we will write a short script to obtain that ID from the Slack API.</p>
<h2>Obtaining Our Bot’s ID</h2>
<p>It is <em>finally</em> time to write some Python code! We'll get warmed up by coding
a short Python script to obtain StarterBot's ID. The ID varies based on the
Slack team. </p>
<p>We need the ID because it allows our application to determine if messages
parsed from the Slack RTM are directed at StarterBot. Our script also
tests that our <code>SLACK_BOT_TOKEN</code> environment variable is properly set. </p>
<p>Create a new file named <code>print_bot_id.py</code> and fill it with the following
code.</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">from</span> <span class="nn">slackclient</span> <span class="kn">import</span> <span class="n">SlackClient</span>
<span class="n">BOT_NAME</span> <span class="o">=</span> <span class="s">&#39;starterbot&#39;</span>
<span class="n">slack_client</span> <span class="o">=</span> <span class="n">SlackClient</span><span class="p">(</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;SLACK_BOT_TOKEN&#39;</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">api_call</span> <span class="o">=</span> <span class="n">slack_client</span><span class="o">.</span><span class="n">api_call</span><span class="p">(</span><span class="s">&quot;users.list&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">api_call</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;ok&#39;</span><span class="p">):</span>
<span class="c"># retrieve all users so we can find our bot</span>
<span class="n">users</span> <span class="o">=</span> <span class="n">api_call</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;members&#39;</span><span class="p">)</span>
<span class="k">for</span> <span class="n">user</span> <span class="ow">in</span> <span class="n">users</span><span class="p">:</span>
<span class="k">if</span> <span class="s">&#39;name&#39;</span> <span class="ow">in</span> <span class="n">user</span> <span class="ow">and</span> <span class="n">user</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)</span> <span class="o">==</span> <span class="n">BOT_NAME</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;Bot ID for &#39;&quot;</span> <span class="o">+</span> <span class="n">user</span><span class="p">[</span><span class="s">&#39;name&#39;</span><span class="p">]</span> <span class="o">+</span> <span class="s">&quot;&#39; is &quot;</span> <span class="o">+</span> <span class="n">user</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;id&#39;</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;could not find bot user with the name &quot;</span> <span class="o">+</span> <span class="n">BOT_NAME</span><span class="p">)</span>
</pre></div>
<p>Our code imports the SlackClient and instantiates it with our
<code>SLACK_BOT_TOKEN</code>, which we set as an environment variable. When the
script is executed by the <code>python</code> command we call the Slack API to list
all Slack users and get the ID for the one that matches the name "starterbot".</p>
<p>We only need to run this script once to obtain our bot’s ID.</p>
<div class="highlight"><pre>python print_bot_id.py
</pre></div>
<p>The script prints a single line of output when it is run that provides
us with our bot's ID.</p>
<p><img src="/source/static/img/160604-simple-python-slack-bot/printed-bot-id.png" width="100%" class="technical-diagram img-rounded" alt="Use the Python script to print the Slack bot's ID in your Slack team."></p>
<p>Copy the unique ID that your script prints out. Export the ID as an
environment variable named <code>BOT_ID</code>.</p>
<div class="highlight"><pre>(starterbot)$ export BOT_ID=&#39;bot id returned by script&#39;
</pre></div>
<p>The script only needs to be run once to get the bot ID. We can now use
that ID in our Python application that will run StarterBot.</p>
<h2>Coding Our StarterBot</h2>
<p>We've got everything we need to write the StarterBot code. Create a new file
named <code>starterbot.py</code> and include the following code in it.</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">from</span> <span class="nn">slackclient</span> <span class="kn">import</span> <span class="n">SlackClient</span>
</pre></div>
<p>The <code>os</code> and <code>SlackClient</code> imports will look familiar because we used them
in the <code>print_bot_id.py</code> program.</p>
<p>With our dependencies imported we can use them to obtain the environment
variable values and then instantiate the Slack client.</p>
<div class="highlight"><pre><span class="cp"># starterbot&#39;s ID as an environment variable</span>
<span class="n">BOT_ID</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">&quot;BOT_ID&quot;</span><span class="p">)</span>
<span class="cp"># constants</span>
<span class="n">AT_BOT</span> <span class="o">=</span> <span class="s">&quot;&lt;@&quot;</span> <span class="o">+</span> <span class="n">BOT_ID</span> <span class="o">+</span> <span class="s">&quot;&gt;:&quot;</span>
<span class="n">EXAMPLE_COMMAND</span> <span class="o">=</span> <span class="s">&quot;do&quot;</span>
<span class="cp"># instantiate Slack &amp; Twilio clients</span>
<span class="n">slack_client</span> <span class="o">=</span> <span class="n">SlackClient</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="err">&#39;</span><span class="n">SLACK_BOT_TOKEN</span><span class="err">&#39;</span><span class="p">))</span>
</pre></div>
<p>The code instantiates the <code>SlackClient</code> client with our <code>SLACK_BOT_TOKEN</code>
exported as an environment variable. </p>
<div class="highlight"><pre>if __name__ == &quot;__main__&quot;:
READ_WEBSOCKET_DELAY = 1 # 1 second delay between reading from firehose
if slack_client.rtm_connect():
print(&quot;StarterBot connected and running!&quot;)
while True:
command, channel = parse_slack_output(slack_client.rtm_read())
if command and channel:
handle_command(command, channel)
time.sleep(READ_WEBSOCKET_DELAY)
else:
print(&quot;Connection failed. Invalid Slack token or bot ID?&quot;)
</pre></div>
<p>The Slack client connects to the Slack RTM API WebSocket then constantly
loops while parsing messages from the firehose. If any of those messages are
directed at StarterBot, a function named <code>handle_command</code> determines what
to do.</p>
<p>Next add two new functions to parse Slack output and handle commands.</p>
<div class="highlight"><pre><span class="nx">def</span> <span class="nx">handle_command</span><span class="p">(</span><span class="nx">command</span><span class="p">,</span> <span class="nx">channel</span><span class="p">)</span><span class="o">:</span>
<span class="s2">&quot;&quot;&quot;</span>
<span class="s2"> Receives commands directed at the bot and determines if they</span>
<span class="s2"> are valid commands. If so, then acts on the commands. If not,</span>
<span class="s2"> returns back what it needs for clarification.</span>
<span class="s2"> &quot;&quot;&quot;</span>
<span class="nx">response</span> <span class="o">=</span> <span class="s2">&quot;Not sure what you mean. Use the *&quot;</span> <span class="o">+</span> <span class="nx">EXAMPLE_COMMAND</span> <span class="o">+</span> <span class="o">\</span>
<span class="s2">&quot;* command with numbers, delimited by spaces.&quot;</span>
<span class="k">if</span> <span class="nx">command</span><span class="p">.</span><span class="nx">startswith</span><span class="p">(</span><span class="nx">EXAMPLE_COMMAND</span><span class="p">)</span><span class="o">:</span>
<span class="nx">response</span> <span class="o">=</span> <span class="s2">&quot;Sure...write some more code then I can do that!&quot;</span>
<span class="nx">slack_client</span><span class="p">.</span><span class="nx">api_call</span><span class="p">(</span><span class="s2">&quot;chat.postMessage&quot;</span><span class="p">,</span> <span class="nx">channel</span><span class="o">=</span><span class="nx">channel</span><span class="p">,</span>
<span class="nx">text</span><span class="o">=</span><span class="nx">response</span><span class="p">,</span> <span class="nx">as_user</span><span class="o">=</span><span class="nx">True</span><span class="p">)</span>
<span class="nx">def</span> <span class="nx">parse_slack_output</span><span class="p">(</span><span class="nx">slack_rtm_output</span><span class="p">)</span><span class="o">:</span>
<span class="s2">&quot;&quot;&quot;</span>
<span class="s2"> The Slack Real Time Messaging API is an events firehose.</span>
<span class="s2"> this parsing function returns None unless a message is</span>
<span class="s2"> directed at the Bot, based on its ID.</span>
<span class="s2"> &quot;&quot;&quot;</span>
<span class="nx">output_list</span> <span class="o">=</span> <span class="nx">slack_rtm_output</span>
<span class="k">if</span> <span class="nx">output_list</span> <span class="nx">and</span> <span class="nx">len</span><span class="p">(</span><span class="nx">output_list</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="o">:</span>
<span class="k">for</span> <span class="nx">output</span> <span class="k">in</span> <span class="nx">output_list</span><span class="o">:</span>
<span class="k">if</span> <span class="nx">output</span> <span class="nx">and</span> <span class="s1">&#39;text&#39;</span> <span class="k">in</span> <span class="nx">output</span> <span class="nx">and</span> <span class="nx">AT_BOT</span> <span class="k">in</span> <span class="nx">output</span><span class="cp">[</span><span class="s1">&#39;text&#39;</span><span class="cp">]</span><span class="o">:</span>
<span class="err">#</span> <span class="k">return</span> <span class="nx">text</span> <span class="nx">after</span> <span class="nx">the</span> <span class="err">@</span> <span class="nx">mention</span><span class="p">,</span> <span class="nx">whitespace</span> <span class="nx">removed</span>
<span class="k">return</span> <span class="nx">output</span><span class="cp">[</span><span class="s1">&#39;text&#39;</span><span class="cp">]</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="nx">AT_BOT</span><span class="p">)</span><span class="cp">[</span><span class="mi">1</span><span class="cp">]</span><span class="p">.</span><span class="nx">strip</span><span class="p">().</span><span class="nx">lower</span><span class="p">(),</span> <span class="o">\</span>
<span class="nx">output</span><span class="cp">[</span><span class="s1">&#39;channel&#39;</span><span class="cp">]</span>
<span class="k">return</span> <span class="nx">None</span><span class="p">,</span> <span class="nx">None</span>
</pre></div>
<p>The <code>parse_slack_output</code> function takes messages from Slack and determines
if they are directed at our StarterBot. Messages that start with a direct
command to our bot ID are then handled by our code - which is currently
just posts a message back in the Slack channel telling the user to write
some more Python code!</p>
<p>Here is how the entire program should look when it's all put together
(you can also
<a href="https://github.com/makaimc/slack-starterbot/blob/master/starterbot.py">view the file in GitHub</a>):</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">from</span> <span class="nn">slackclient</span> <span class="kn">import</span> <span class="n">SlackClient</span>
<span class="c"># starterbot&#39;s ID as an environment variable</span>
<span class="n">BOT_ID</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">&quot;BOT_ID&quot;</span><span class="p">)</span>
<span class="c"># constants</span>
<span class="n">AT_BOT</span> <span class="o">=</span> <span class="s">&quot;&lt;@&quot;</span> <span class="o">+</span> <span class="n">BOT_ID</span> <span class="o">+</span> <span class="s">&quot;&gt;:&quot;</span>
<span class="n">EXAMPLE_COMMAND</span> <span class="o">=</span> <span class="s">&quot;do&quot;</span>
<span class="c"># instantiate Slack &amp; Twilio clients</span>
<span class="n">slack_client</span> <span class="o">=</span> <span class="n">SlackClient</span><span class="p">(</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;SLACK_BOT_TOKEN&#39;</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">handle_command</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">channel</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Receives commands directed at the bot and determines if they</span>
<span class="sd"> are valid commands. If so, then acts on the commands. If not,</span>
<span class="sd"> returns back what it needs for clarification.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">response</span> <span class="o">=</span> <span class="s">&quot;Not sure what you mean. Use the *&quot;</span> <span class="o">+</span> <span class="n">EXAMPLE_COMMAND</span> <span class="o">+</span> \
<span class="s">&quot;* command with numbers, delimited by spaces.&quot;</span>
<span class="k">if</span> <span class="n">command</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">EXAMPLE_COMMAND</span><span class="p">):</span>
<span class="n">response</span> <span class="o">=</span> <span class="s">&quot;Sure...write some more code then I can do that!&quot;</span>
<span class="n">slack_client</span><span class="o">.</span><span class="n">api_call</span><span class="p">(</span><span class="s">&quot;chat.postMessage&quot;</span><span class="p">,</span> <span class="n">channel</span><span class="o">=</span><span class="n">channel</span><span class="p">,</span>
<span class="n">text</span><span class="o">=</span><span class="n">response</span><span class="p">,</span> <span class="n">as_user</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">parse_slack_output</span><span class="p">(</span><span class="n">slack_rtm_output</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> The Slack Real Time Messaging API is an events firehose.</span>
<span class="sd"> this parsing function returns None unless a message is</span>
<span class="sd"> directed at the Bot, based on its ID.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">output_list</span> <span class="o">=</span> <span class="n">slack_rtm_output</span>
<span class="k">if</span> <span class="n">output_list</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">output_list</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">for</span> <span class="n">output</span> <span class="ow">in</span> <span class="n">output_list</span><span class="p">:</span>
<span class="k">if</span> <span class="n">output</span> <span class="ow">and</span> <span class="s">&#39;text&#39;</span> <span class="ow">in</span> <span class="n">output</span> <span class="ow">and</span> <span class="n">AT_BOT</span> <span class="ow">in</span> <span class="n">output</span><span class="p">[</span><span class="s">&#39;text&#39;</span><span class="p">]:</span>
<span class="c"># return text after the @ mention, whitespace removed</span>
<span class="k">return</span> <span class="n">output</span><span class="p">[</span><span class="s">&#39;text&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">AT_BOT</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span> \
<span class="n">output</span><span class="p">[</span><span class="s">&#39;channel&#39;</span><span class="p">]</span>
<span class="k">return</span> <span class="bp">None</span><span class="p">,</span> <span class="bp">None</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">READ_WEBSOCKET_DELAY</span> <span class="o">=</span> <span class="mi">1</span> <span class="c"># 1 second delay between reading from firehose</span>
<span class="k">if</span> <span class="n">slack_client</span><span class="o">.</span><span class="n">rtm_connect</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;StarterBot connected and running!&quot;</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">command</span><span class="p">,</span> <span class="n">channel</span> <span class="o">=</span> <span class="n">parse_slack_output</span><span class="p">(</span><span class="n">slack_client</span><span class="o">.</span><span class="n">rtm_read</span><span class="p">())</span>
<span class="k">if</span> <span class="n">command</span> <span class="ow">and</span> <span class="n">channel</span><span class="p">:</span>
<span class="n">handle_command</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">channel</span><span class="p">)</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">READ_WEBSOCKET_DELAY</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;Connection failed. Invalid Slack token or bot ID?&quot;</span><span class="p">)</span>
</pre></div>
<p>Now that all of our code is in place we can run our StarterBot on the
command line with the <code>python starterbot.py</code> command.</p>
<p><img src="/source/static/img/160604-simple-python-slack-bot/starterbot-running.png" width="100%" class="technical-diagram img-rounded" alt="Console output when the StarterBot is running and connected to the API."></p>
<p>In Slack, create a new channel and invite StarterBot or invite it to an
existing channel.</p>
<p><img src="/source/static/img/160604-simple-python-slack-bot/create-channel.png" width="100%" class="technical-diagram img-rounded" alt="In the Slack user interface create a new channel and invite StarterBot."></p>
<p>Now start giving StarterBot commands in your channel.</p>
<p><img src="/source/static/img/160604-simple-python-slack-bot/working-starterbot.png" width="100%" class="technical-diagram img-rounded" alt="Give StarterBot commands in your Slack channel."></p>
<h2>Wrapping Up</h2>
<p>Alright, now you've got a simple StarterBot with a bunch of places in the
code you can add whatever features you want to build. </p>
<p>There is a whole lot more that could be done using the Slack RTM API and Python.
Check out these posts to learn what you could do:</p>
<ul>
<li>Attach a persistent <a href="/databases.html">relational database</a> or
<a href="/no-sql-datastore.html">NoSQL back-end</a> such as
<a href="/postgresql.html">PostgreSQL</a>, <a href="/mysql.html">MySQL</a> or <a href="/sqlite.html">SQLite</a>
to save and retrieve user data</li>
<li>Add another channel to interact with the bot
<a href="https://www.twilio.com/blog/2016/05/build-sms-slack-bot-python.html">via SMS</a>
or
<a href="https://www.twilio.com/blog/2016/05/add-phone-calling-slack-python.html">phone calls</a></li>
<li><a href="/api-integration.html">Integrate other web APIs</a> such as
<a href="https://developer.github.com/v3/">GitHub</a>,
<a href="https://www.twilio.com/docs">Twilio</a> or <a href="https://docs.api.ai/">api.ai</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 with
the username <a href="https://github.com/makaimc">makaimc</a>.</p>
<p>Something wrong with this post? Fork
<a href="https://github.com/makaimc/fullstackpython.com/blob/gh-pages/source/content/posts/160604-build-first-slack-bot-python.markdown">this page's source on GitHub</a>.</p></description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Makai</dc:creator><pubDate>Sat, 04 Jun 2016 00:00:00 -0400</pubDate><guid>tag:www.fullstackpython.com,2016-06-04:build-first-slack-bot-python.html</guid></item><item><title>Responding to SMS Text Messages with Python & Flask</title><link>https://www.fullstackpython.com/respond-sms-text-messages-python-flask.html</link><description><p>Short Message Service (SMS) text messages are
<a href="/blog/send-sms-text-messages-python.html">easy to send from Python applications</a>
with a
<a href="/application-programming-interfaces.html">web application programming interface (API)</a>.
Flask applications can also receive incoming text messages and respond
back to the sender with just a few lines of Python code.</p>
<h2>Tools We Need</h2>
<p>This tutorial is fine for both Python 2 and 3. Make sure you have one of
those two versions installed on your system.</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/latest/">virtualenv</a> to handle
<a href="/application-dependencies.html">application dependencies</a></li>
<li>The <a href="/flask.html">Flask</a> micro web framework</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/sending-messages">SMS web API</a></li>
<li>Open source
<a href="https://pypi.python.org/pypi/twilio">Twilio Python helper library</a></li>
<li><a href="https://ngrok.com/">Ngrok</a> for localhost tunneling to our Flask
application while it's running on our local development environment</li>
</ul>
<p>If you need assistance getting pip and virtualenv installed, take a look at
the first few steps in the
<a href="/blog/python-3-flask-green-unicorn-ubuntu-1604-xenial-xerus.html">how to set up Python 3, Flask and Green Unicorn on Ubuntu 16.04 LTS</a>
guide, which shows how to install system packages for those tools.</p>
<h2>Installing Our Dependencies</h2>
<p>Our code will use a helper library to make it easier to respond to text
messages from Python. The helper library dependency along with the Flask
code library can be installed from <a href="https://pypi.python.org/pypi">PyPI</a> into
a virtualenv. In your terminal use the following command to generate a new
virtualenv. </p>
<div class="highlight"><pre>virtualenv respondsms
</pre></div>
<p>Activate the virtualenv.</p>
<div class="highlight"><pre>source respondsms/bin/activate
</pre></div>
<p>The command prompt will change after we properly activate the virtualenv
to something like this:</p>
<p><img src="/source/static/img/160530-respond-sms-python-flask/activate-virtualenv.png" width="100%" class="technical-diagram img-rounded"></p>
<p>Install Flask and the Twilio Python helper library into the virtualenv with
the <code>pip</code> command. </p>
<div class="highlight"><pre>pip install flask twilio
</pre></div>
<p>The dependencies are installed so that we can use it with our Python code.
Now we can write our Python application.</p>
<h2>Building Our Flask Web App</h2>
<p>Our Flask application will have two routes: one to make sure the web app
is running and another that handles incoming HTTP POST requests. Create
a new file named <code>app.py</code> in your home directory or where you choose to
store your Python project files.</p>
<p>Within <code>app.py</code> write the following code. You can also see
<a href="https://gist.github.com/makaimc/8ab434ccb604d3ba5bde817a183e0bde">this code in a GitHub Gist</a>
if that's easier to copy and paste.</p>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span><span class="p">,</span> <span class="n">Response</span><span class="p">,</span> <span class="n">request</span>
<span class="kn">from</span> <span class="nn">twilio</span> <span class="kn">import</span> <span class="n">twiml</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
<span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/&quot;</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="n">Response</span><span class="p">(</span><span class="s">&quot;It works!&quot;</span><span class="p">),</span> <span class="mi">200</span>
<span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/twilio&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s">&quot;POST&quot;</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">inbound_sms</span><span class="p">():</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="c"># we get the SMS message from the request. we could also get the </span>
<span class="c"># &quot;To&quot; and the &quot;From&quot; phone number as well</span>
<span class="n">inbound_message</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">form</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">response</span><span class="o">.</span><span class="n">message</span><span class="p">(</span><span class="s">&quot;Hello back to you!&quot;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">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="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="n">mimetype</span><span class="o">=</span><span class="s">&quot;application/xml&quot;</span><span class="p">),</span> <span class="mi">200</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">app</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">debug</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
</pre></div>
<p>The inline comments on the lines starting with <code>#</code> explain what the lines
below them do. Flask applications define URL routes with the <code>@app.route</code>
decorator. Our application needs two routes therefore we have two of those
decorators defined.</p>
<p>Give the application a try by running it with <code>python app.py</code>. If you have
trouble running the program, make sure your virtualenv is still active so
that the application can use the Flask and Twilio code libraries we installed
earlier.</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/160530-respond-sms-python-flask/app-local.jpg" width="100%" class="technical-diagram img-rounded"></p>
<p>There is one problem with our application running on our local development
environment: there's no way for our server to receive HTTP POST requests
unless we use a localhost tunnel.</p>
<h2>Localhost Tunneling with Ngrok</h2>
<p><a href="https://ngrok.com">Ngrok</a> provides a localhost tunnel so that outside
services can connect to a server running in your local development
environment. Download and install Ngrok.</p>
<p>We can now run Ngrok locally and connect our Flask app running on port 5000.
Within the directory where you extracted Ngrok, run this command.</p>
<div class="highlight"><pre>./ngrok http 5000
</pre></div>
<p><img src="/source/static/img/160530-respond-sms-python-flask/start-ngrok.jpg" width="100%" class="technical-diagram img-rounded"></p>
<p>Awesome, now we can use that Ngrok Forwarding URL to access our application
from any machine that has an internet connection. Replace the URL in the
web browser with your own Forwarding URL, like I did in this screenshot.</p>
<p><img src="/source/static/img/160530-respond-sms-python-flask/access-ngrok.png" width="100%" class="technical-diagram img-rounded"></p>
<p>We just need a phone number that'll hit our application with a POST request
to respond to text messages.</p>
<h2>Obtaining Our Phone Number</h2>
<p>We can use our Flask application's route to respond to incoming web API
requests based on incoming SMS messages to a Twilio phone number. Go to the
<a href="https://www.twilio.com/try-twilio">Twilio website and sign up for a free trial account</a>
to use their API. If you already have a Twilio account then sign into your
existing account.</p>
<p><img src="/source/static/img/160530-respond-sms-python-flask/try-twilio.png" width="100%" class="technical-diagram img-rounded"></p>
<p>The Twilio trial account allows you to send and receive text messages to
your own validated phone number. To send and respond 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 responding to
inbound text messages.</p>
<p>Scroll down to near the bottom of the page and look for the "Messaging"
header. Modify the "A Message Comes in" text box so that it has your
ngrok Forwarding URL plus the "/twilio" route, as shown in this screenshot.</p>
<p><img src="/source/static/img/160530-respond-sms-python-flask/number-configuration.png" width="100%" class="technical-diagram img-rounded"></p>
<p>Now press the red "Save" button at the bottom to make 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/160530-respond-sms-python-flask/success.jpg" width="100%" class="technical-diagram img-rounded"></p>
<p>This simple Flask application is a good start to build more complicated
responses such as
<a href="https://www.twilio.com/blog/2014/06/using-natural-language-processing-for-better-sms-interfaces-using-twilio-and-pythons-textblob.html">adding natural language processing</a>,
<a href="https://www.twilio.com/blog/2016/05/build-sms-slack-bot-python.html">building SMS Slack bots</a>
or
<a href="https://www.twilio.com/blog/2015/08/romram-hacking-building-an-sms-powered-game-genie-with-lua-and-python.html">coding SMS-powered NES Game Genies</a>.</p>
<h2>What's next?</h2>
<p>Sweet, now our Flask web app automatically responds to incoming SMS text
messages! It's pretty crazy to think that entire businesses such as
<a href="http://techcrunch.com/2016/03/07/superphone/">SuperPhone</a> and
<a href="https://www.remind.com/">Remind</a> are built off code that started out very
similar to the code we just wrote.</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/makaimc">makaimc</a>.</p>
<p>Something wrong with this post? Fork
<a href="https://github.com/makaimc/fullstackpython.com/blob/gh-pages/source/content/posts/160530-respond-sms-text-messages-python-flask.markdown">this page's source on GitHub</a>.</p></description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Matt Makai</dc:creator><pubDate>Mon, 30 May 2016 00:00:00 -0400</pubDate><guid>tag:www.fullstackpython.com,2016-05-30:respond-sms-text-messages-python-flask.html</guid></item><item><title>How to Install and Use MySQL on Ubuntu 16.04</title><link>https://www.fullstackpython.com/install-mysql-ubuntu-1604.html</link><description><p><a href="/mysql.html">MySQL</a> is a common open source
<a href="/databases.html">relational database</a> for creating, reading, updating
and deleting data in <a href="/web-frameworks.html">Python web applications</a>.
Let's learn how to install MySQL on <a href="/ubuntu.html">Ubuntu 16.04</a> and then
run a few SQL queries within the command line client.</p>
<p>We will not go over connecting via Python applications using
<a href="/object-relational-mappers-orms.html">object-relational mappers (ORMs)</a>
but these steps can be used as a prerequisite to working with an ORM such
as SQLAlchemy or Peewee.</p>
<h2>Tools We Need</h2>
<p>In this tutorial we'll use the following components:</p>
<ul>
<li><a href="http://releases.ubuntu.com/16.04/">Ubuntu 16.04</a> (this tutorial
should also work on other Ubuntu versions)</li>
<li><a href="http://dev.mysql.com/doc/">MySQL</a></li>
</ul>
<h2>Install MySQL</h2>
<p>We can install MySQL by using the <code>apt</code> package manager. First make sure
your packages list are up to date. Open the terminal and run this <code>apt</code>
command.</p>
<div class="highlight"><pre>sudo apt-get update
</pre></div>
<p>We need to install the <code>mysql-server</code> package, which downloads the required
files, configures the initial database set up and handles running MySQL