server-side web programming: python (part 2) · objectives • you will learn about: – python...
TRANSCRIPT
Server-Side Web Programming: Python (Part 2)
Copyright © 2017 by Robert M. Dondero, Ph.D
Princeton University
1
Objectives
• You will learn about: – Python WSGI programming – Web app frameworks in general (briefly) – The Bottle web app framework
• The MVC architecture
2
CGI Problem
• Problem: CGI apps are slow – For each request, HTTP server forks/execs a
new process – OK for low-volume website – Maybe not OK for high-volume website
4
CGI Example
6
Browser Process
HTTP Server Process
request for searchform page
Browser process asks HTTP server process for searchform page
CGI Example
7
Browser Process
HTTP Server Process
searchform Process
request for searchform page
HTTP server process forks child process, execs searchform program
CGI Example
8
Browser Process
HTTP Server Process
searchform page
Searchform process passes searchform page to HTTP server process Searchform process exits
searchform Process
CGI Example
9
Browser Process
HTTP Server Process
searchform page
HTTP server process passes searchform page to browser
CGI Example
10
Browser Process
HTTP Server Process
request for searchresults page
Browser process asks HTTP server process for searchresults page
CGI Example
11
Browser Process
HTTP Server Process
searchresultsProcess
request for searchresults page
HTTP server process forks child process, execs searchresults program
CGI Example
12
Browser Process
HTTP Server Process
searchresults page
Searchresults process passes searchresults page to HTTP server process Searchresults process exits
searchresults Process
CGI Example
13
Browser Process
HTTP Server Process
searchresults page
HTTP server process passes searchresults page to browser
Embedding
• Solution 1: Embed apps in HTTP server process – HTTP server does not fork processes – HTTP server spawns threads in its process
• (See Threads lecture later in course)
14
Embedding Example
15
Browser Process
HTTP Server Process
Browser process asks HTTP server process for searchform page
request for searchform page
Embedding Example
16
Browser Process
HTTP Server Process
HTTP server process spawns new thread (See upcoming Threads lecture) Thread generates searchform page
searchform Thread
Embedding Example
17
Browser Process
HTTP Server Process
Searchform thread exits HTTP server process sends searchform page to browser process
searchform Thread
searchform page
Embedding Example
18
Browser Process
HTTP Server Process
Browser process asks HTTP server process for searchresults page
request for searchresults page
Embedding Example
19
Browser Process
HTTP Server Process
HTTP server process spawns new thread Thread generates searchresults page
searchresultsThread
Embedding Example
20
Browser Process
HTTP Server Process
Searchresults thread exits HTTP server process sends searchresults page to browser process
searchresultsThread
searchresults page
Embedding Assessment • Embedding assessment (simplified):
– (pro) Faster than CGI • Spawning a tread is faster than forking a process
– (con) Inflexible • Poor load balancing; better for HTTP server to
delegate work to pool of app servers, maybe running on distinct computers
– (con) Insecure • HTTP server typically runs as root • Apps run with same permissions as HTTP server
21
Fast CGI
• Solution 2: Fast CGI – HTTP server forks processes
• As with CGI • Typically one for each app
– Processes persist • Unlike CGI
22
Fast CGI Example
24
Browser Process
HTTP Server Process
request for searchform page
Browser process asks HTTP server process for searchform page
Fast CGI Example
25
Browser Process
HTTP Server Process
Penny Process
request for searchform page
HTTP server process forks child process, execs Penny program
Fast CGI Example
26
Browser Process
HTTP Server Process
searchform page
Penny process passes searchform page to HTTP server process Penny process persists
Penny Process
Fast CGI Example
27
Browser Process
HTTP Server Process
searchform page
HTTP server process passes searchform page to browser
Penny Process
Fast CGI Example
28
Browser Process
HTTP Server Process
request for searchresults page
Browser process asks HTTP server process for searchresults page
Penny Process
Fast CGI Example
29
Browser Process
HTTP Server Process
Penny Process
request for searchresults page
HTTP server process sends request to existing Penny process
Fast CGI Example
30
Browser Process
HTTP Server Process
searchresults page
Penny process passes searchresults page to HTTP server process Penny process persists
Penny Process
Fast CGI Example
31
Browser Process
HTTP Server Process
searchresults page
HTTP server process passes searchresults page to browser
Penny Process
Fast CGI Assessment
• Fast CGI assessment (simplified): – (pro) Faster than CGI – (pro) Flexible
• Good load balancing; HTTP server can delegate work to pool of app servers, maybe running on different computers
• Etc. – (pro) Secure
• Apps can run with more limited permissions than HTTP server has
32
Python Solution: WSGI
• Python solution:
• Web Server Gateway Interface (WSGI) – A specification of two interfaces…
33
Python Solution: WSGI
Browser HTTP Server
Your App
WSGI server-side Defines messages your app Can send to HTTP server
WSGI client-side Defines messages HTTP server can send to your app
Environment info
Callback function
Response via callback function
34
Python Solution: WSGI
Browser
HTTP Server
Your App
Optional middleware provides: App persistence (as with fast CGI) Load balancing among multiple app processes Maybe on multiple computers Authentication …
WSGI Middleware
WSGI Middleware
35
Recall Decorator pattern
Python Solution: WSGI
• Web Server Gateway Interface (WSGI) – Allows architectural flexibility
• Unknown to web app developer
– Facilitates separation of concerns: • Programmers (and others) compose web apps • System administrators deploy web apps
• The way to structure Python web apps
36
PennyPythonWsgi App
• See PennyPythonWsgi app – penny.sql, penny.sqlite, book.py, database.py – runserver – runserver.bat – common.py – penny.py
37
PennyPythonWsgi App
• Observation: – Programmers don’t use WSGI directly – Instead:
• Programmers use web app frameworks • Many Python web app frameworks use WSGI
• Suggestion: – Don’t be concerned about WSGI details – …Unless you intend to compose a Python
web app framework!
38
Motivation for Frameworks
• Ancient approach to building a website: – Write ad hoc client-side code
• In HTML, CSS, JavaScript, etc.
– Write ad hoc server-side code • In Python, Java, PHP, etc. • Write ad hoc code to access DB
40
Motivation for Frameworks
• Problem: – Common patterns within and among web apps – Replicated code within and among web apps – Web app development involves lots of tedious/
replicated effort • Solution:
– Web app frameworks • Web app frameworks mechanize (parts of) the
development process
41
Popular Frameworks Stack Github Overflow Overall Score Score Score
ASP.NET (C#) 100 100 AngularJS (Javascript) 97 97 97 Ruby on Rails (Ruby) 93 98 95 ASP.NET MVC (C#) 94 94 React (JavaScript) 100 84 92 Django (Python) 90 93 91 Laravel (PHP) 92 87 89 Angular (JavaScript) 89 86 87 Spring (Java) 84 91 87 Express (JavaScript) 92 82 87 Meteor (JavaScript) 93 80 86 CodeIgniter (PHP) 84 86 85 Symfony (PHP) 84 85 84 Vue.js (JavaScript) 98 69 83 Flask (Python) 90 76 83
According to h,ps://ho1rameworks.com/ on 6/21/17
42
Popular Frameworks Stack Github Overflow Overall Score Score Score
Ember.js (JavaScript) 86 78 82 JSF (Java) 82 82 Flex (ActionScript) 79 79 CakePHP (PHP) 76 80 78 Google Web Toolkit (Java) 78 78 Play (Scala) 79 75 77 Zend (PHP) 74 78 76 Sails.js (JavaScript) 85 67 76 Yii (PHP) 72 76 74 Tornado (Python) 83 62 72 Sinatra (Ruby) 79 66 72 Grails (Groovy) 64 80 72 Aurelia (JavaScript) 79 61 70 Phoenix (Elixir) 79 60 69 Phalcon (PHP) 78 58 68
According to h,ps://ho1rameworks.com/ on 6/21/17
43
Popular Frameworks Stack Github Overflow Overall Score Score Score
Koa (JavaScript) 84 49 66 Dropwizard (Java) 74 56 65 Struts (Java) 64 64 Bottle (Python) 74 55 63 Wicket (Java) 63 63 Dojo (JavaScript) 56 71 63 Nancy (C#) 73 54 63 Vert.x (Java) 75 51 63 web.py (Python) 71 53 62 Elm (Elm) 70 54 62 Pyramid (Python) 65 59 62 Vapor (Swift) 80 40 60 beego (Go) 81 40 60 Gin (Go) 80 41 60 Kohana (PHP) 61 60 60 …
According to h,ps://ho1rameworks.com/ on 6/21/17
44
Popular Python Frameworks
• According to https://hotframeworks.com/ on 6/21/17…
• Some popular Python frameworks: – Django, Flask*, Tornado, Bottle*, web.py,
Pyramid, web2py, CherryPy*, Grok, Zope
– * micro-framework
45
Popular Java Frameworks
• According to https://hotframeworks.com/ on 6/21/17…
• Some popular Java frameworks: – Spring MVC, JSF, Google Web Toolkit,
Dropwizard, Struts, Wicket, Vert.x, Vaadin
46
Popular PHP Frameworks
• According to https://hotframeworks.com/ on 6/21/17…
• Some popular PHP frameworks: – Laravel, CodeIgniter, Symfony, CakePHP,
Zend, Yii
47
Framework Assessment
• Positives – Yield reliable code
• Framework code has been thoroughly tested
– Yield consistent code • Code has uniform structure across apps
– Make efficient use of programmer time • Framework handles repetitive parts • “DRY” (don’t repeat yourself) is encouraged
48
Framework Assessment • Negatives
– Can yield systems that are: • Large • Slow
• See Joel Spolsky’s Why I Hate Frameworks – http://discuss.joelonsoftware.com/default.asp?
joel.3.219431.12
49
The Bottle Web App Framework
• Who: Marcel Hellkamp • Descrip: “Bottle is a fast,
simple and lightweight WSGI micro web-framework for Python. It is distributed as a single file module and has no dependencies other than the Python Standard Library.” -- Wikipedia
51
Why Bottle? • Why study Bottle?
– (Instead of some other Python framework) – Easy to learn
• Simple (“micro-framework”) • Good documentation and tutorial
– Reasonable to use for Assignments 3 & 4 • Installed on CourseLab • Easy to install on your personal computer • Has test web server • Allows flat directory structure; easy to submit
• P.S. I have Penny in Django; ask if you want it
52
PennyBottle1Fund App
• See PennyBottle1Fund App – penny.sql, penny.sqlite, book.py, database.py – runserver – runserver.bat – common.py – penny.py
• Generalizing...
53
PennyBottle1Fund App
• Bottle separates URL from file name – (Unlike CGI) – Can use “pretty” URLs
• Bottle separates URL from function name – Can map multiple URLs to same function – Can change function name without changing
URL, or vice versa
54
PennyBottle1Fund App
• Bottle provides utility functions – Functions to fetch “name=value” pairs – Functions to fetch/create cookies – Function to implement HTTP redirect
55
Aside: Python Decorators
56
def sqr(i): return i * i def main(): print sqr(5) if __name__ == '__main__': main()
Wanted: sqr() prints “sqr was called” each time it is called
Aside: Python Decorators
57
def sqr(i): print 'sqr was called' return i * i def main(): print sqr(5) if __name__ == '__main__': main()
OK, but… Doesn’t generalize Requires edit of def of sqr()
Aside: Python Decorators
58
def printNameDecorator(f): def fwrapper(i): print f.__name__, 'was called' return f(i) return fwrapper def sqr(i): return i * i sqr = printNameDecorator(sqr) def main(): print sqr(5) if __name__ == '__main__': main()
Prints: sqr was called 25
One approach:
Aside: Python Decorators
59
def printNameDecorator(f): def fwrapper(i): print f.__name__, 'was called' return f(i) return fwrapper @printNameDecorator def sqr(i): return i * i def main(): print sqr(5) if __name__ == '__main__': main()
Prints: sqr was called 25
Using a decorator
PennyBottle1Fund App
60
Bottle uses Python decorators
... @route('/searchform') def searchForm(): ... ...
... def searchForm(): ... searchForm = default_app().route( \ path='/searchform', callback=searchForm) ...
Using a decorator
Same code without using a decorator
Toward PennyBottle2Templates
• Problem: – Code contains many assignment statements
to compose HTML code – Bulky; awkward; error prone
• Solution: – Templates
61
PennyBottle2Templates App • See PennyBottle2Templates App
– runserver, runserver.bat, penny.sql, penny.sqlite, book.py, database.py
– header.tpl – footer.tpl – index.tpl – searchform.tpl – searchresults.tpl – penny.py
• Generalizing...
62
PennyBottle2Templates App
• Template (informally) – HTML doc with placeholders – Each placeholder is identified by a key
63
Hello <strong>{{username}}</strong> and welcome
hello.tpl
PennyBottle2Templates App
• To instantiate a template: – template('somefile.tpl', dict)
• dict contains key/value pairs • For each placeholder identified by key in somefile.tpl, replaces the placeholder with the value associated with key in dict
• Returns the resulting str
64
PennyBottle2Templates App
• To instantiate a template: – Example:
65
dict = {'username': 'Bob'} s = template('hello.tpl', dict)
s = 'Hello <strong>Bob</strong> and welcome'
Hello <strong>{{username}}</strong> and welcome hello.tpl
equivalent to
PennyBottle2Templates App
• Template can contain: – Inline expressions
• …{{expr}}… • expr usually is a key in the provided dict
• expr can be any expression that evaluates to a str or has a str representation
66
... {{book.getAuthor()}} ...
... {{prevAuthor}} ...
PennyBottle2Templates App – Embedded pseudo-Python code
• % line of Python code • Indentation is ignored • Blocks that are normally indented must be closed
with end keyword
67
% for book in books: {{book.getAuthor()}}, {{book.getTitle()}}, ${{book.getPrice()}}<br> % end
PennyBottle3Templates App – Includes of other templates
• % include('other.tpl')
68
... % include('header.tpl') ...
Toward PennyBottle3Templates
• Problem??? – Computation of morning/afternoon is in
penny.py; better to move it to header.tpl? – Computation of current time is in penny.py;
better to move it to footer.tpl? • Solution???
– Move more Python code to templates…
69
PennyBottle3Templates App
• See PennyBottle3Templates App – runserver, runserver.bat, penny.sql,
penny.sqlite, book.py, database.py, common.py, index.tpl, searchform.tpl, searchresults.tpl
– header.tpl – footer.tpl – penny.py
• Generalizing...
70
MVC Architecture
• Bottle encourages... • The Model-View-Controller (MVC)
architecture – Model: The system’s data access code – View: The system’s data presentation code – Controller: (vague) The system’s business
code; the logic that connects the model with its view(s)
71
MVC Architecture
• In a Bottle app – Views: template files
• In Penny apps: *.tpl files
– Controller: “main” Python file • In Penny apps: penny.py
– Model: DB-related Python files • In Penny apps: database.py, book.py • Many “non-micro” frameworks facilitate model dev
72
MVC Assessment
• Positives – Allows separation of concerns:
• Model: DB administrator (SQL, normalization, ...) • Views: Web designer (HTML, CSS, ...) • Controller: Programmer (Python, Java, …)
73
MVC Assessment
• Positives (cont.) – Facilitates parallel development
• Can develop model, views, controller concurrently
– Facilitates maintenance • Framework provides loose coupling • (To some extent) can change model, views,
controller independently
74
MVC Suggestions
• Suggestions: – Use MVC!!! – But keep views simple
• Avoid embedded code in views/templates when you reasonably can
• Is PennyBottle3Templates app better or worse than PennyBottle2Templates app?
75
Aside: ORMs
• Problem: Impedence mismatch – Relational DB data model: tables, rows,
columns – OO data model: objects, object composition,
classes, class inheritance – Very different!
76
Aside: ORMs
• Solution 1: Cursor – Relational DB driver fetches (sub)table from
DB, presents it to OO code as a cursor – OO code uses cursor to traverse table
77
Aside: ORMs • Solution 2: Object-relational mappers
(ORMs) – Provided stand-alone (see Wikipedia) – Provided by many full-featured frameworks – Not provided by micro-frameworks (e.g., Bottle) – Through config files, map relational DB tables to
classes/objects – OO code fetches/stores data by sending
messages to objects, not by executing SQL statements
– Facilitates model development
78
Aside: Django and COS 333 • Django
– Use for COS 333 assignments? – (pro) The most popular Python framework – (pro) Has ORM – (con) More complex/powerful than necessary – (con) Requires non-flat directory structure – (con) ORM requires control of DB
• Django’s ORM requires control fields in tables • Could not use Django’s ORM to access Penny DB • Limitation beyond COS 333???
79
More Bottle!
• There is much more to Bottle • Bottle user’s guide:
– http://bottlepy.org/docs/dev/ • Bottle tutorial:
– http://bottlepy.org/docs/dev/tutorial.html
80