This document discusses Python and web frameworks. It begins with an introduction to Python and its advantages for web development. It then discusses several popular Python web frameworks including web.py, Flask, and Django. It also covers related topics like WSGI, templating with Jinja2, asynchronous programming, and deployment with virtualenv.
Python
Web 2.0
QCon Beijing 2010
http://www.flickr.com/photos/arnolouise/2986467632/
2.
About Me
• Python
•2002 Python
• 2004
Python
• http://www.douban.com/
people/hongqn/
• hongqn@douban.com
• http://twitter.com/hongqn
3.
Python
• Python is a programming language that lets you
work more quickly and integrate your systems more
effectively. You can learn to use Python and see
almost immediate gains in productivity and lower
maintenance costs. (via http://python.org/)
4.
Languages in
C
27%
Javascript
12%
C++
Python 3%
58%
(Pyrex/R/Erlang/Go/Shell)
1%
: 13
import os
fromcollections import defaultdict
d = defaultdict(int)
for dirpath, dirnames, filenames in os.walk('.'):
for filename in filenames:
path = os.path.join(dirpath, filename)
ext = os.path.splitext(filename)[1]
d[ext] += len(list(open(path)))
for ext, n_lines in d.items():
print ext, n_lines
Why so manyPython
web frameworks?
• Because you can write your own
framework in 3 hours and a total of 60
lines of Python code.
• http://bitworking.org/news/
Why_so_many_Python_web_frameworks
29.
doctest
def cube(x):
"""
>>> cube(10)
1000
"""
return x * x
def _test():
import doctest
doctest.testmod()
if __name__ == "__main__":
_test()
30.
nose http://somethingaboutorange.com/mrl/projects/nose/
from cube import cube
def test_cube():
result = cube(10)
assert result == 1000
31.
numpy http://numpy.scipy.org/
>>> from numpy import *
>>> A = arange(4).reshape(2, 2)
>>> A
array([[0, 1],
[2, 3]])
>>> dot(A, A.T)
array([[ 1, 3],
[ 3, 13]])
32.
ipython http://numpy.scipy.org/
$ ipython -pylab
In [1]: X = frange(0, 10, 0.1)
In [2]: Y = [sin(x) for x in X]
In [3]: plot(X, Y)
33.
ipython http://numpy.scipy.org/
$ ipython -pylab
In [1]: X = frange(0, 10, 0.1)
In [2]: Y = [sin(x) for x in X]
In [3]: plot(X, Y)
>>> import this
TheZen of Python, by Tim Peters http://bit.ly/pyzencn
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to
break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
38.
In the faceof ambiguity, refuse the
temptation to guess.
There should be one-- and
preferably only one --obvious way
to do it.
Although that way may not be Python
obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than
*right* now.
If the implementation is hard to
explain, it's a bad idea.
If the implementation is easy to
explain, it may be a good idea.
Namespaces are one honking great
idea -- let's do more of those!
39.
Simple is betterthan
complex
class HelloWorld
{
public static void main(String args[])
{
System.out.println("Hello World!");
}
}
Readability counts
• {} end
• (except "@" for
decorators)
if limit is not None and len(ids)>limit:
ids = random.sample(ids, limit)
45.
TOOWTDI
• There (shouldbe) Only One Way To Do It.
• vs. Perlish TIMTOWTDI (There Is More
Than One Way To Do It)
46.
TOOWTDI
• There(should be) Only One Way To Do It.
• vs. Perlish TIMTOWTDI (There Is More
Than One Way To Do It)
a = [1, 2, 3, 4, 5]
b = []
for i in range(len(a)):
b.append(a[i]*2)
47.
TOOWTDI
• There(should be) Only One Way To Do It.
• vs. Perlish TIMTOWTDI (There Is More
Than One Way To Do It)
a = [1, 2, 3, 4, 5]
b = []
for i in range(len(a)):
b.append(a[i]*2)
48.
TOOWTDI
• There(should be) Only One Way To Do It.
• vs. Perlish TIMTOWTDI (There Is More
Than One Way To Do It)
a = [1, 2, 3, 4, 5] b = []
b = [] for x in a:
for i in range(len(a)):
b.append(x*2)
b.append(a[i]*2)
49.
TOOWTDI
• There(should be) Only One Way To Do It.
• vs. Perlish TIMTOWTDI (There Is More
Than One Way To Do It)
a = [1, 2, 3, 4, 5] b = []
b = [] for x in a:
for i in range(len(a)):
b.append(x*2)
b.append(a[i]*2)
50.
TOOWTDI
• There (shouldbe) Only One Way To Do It.
• vs. Perlish TIMTOWTDI (There Is More
Than One Way To Do It)
b = [x*2 for x in a]
def cache(key):
def deco(func):
def _(*args, **kwargs):
r = mc.get(key)
if r is None:
r = func(*args, **kwargs)
mc.set(key, r)
return r
return _
return deco
91.
def cache(key):
def deco(func):
def _(*args, **kwargs):
r = mc.get(key)
if r is None:
r = func(*args, **kwargs)
mc.set(key, r)
return r
return _
return deco
92.
cache key
def get_review(id):
key = 'review:%s' % id
review = mc.get(key)
if review is None: # cache miss
id, author_id, text = exc_sql("select id, author_id,
text from review where id=%s", id)
review = Review(id, author_id, text)
mc.set(key, review)
return review
93.
cache key
decorator
@cache('review:{id}')
def get_review(id):
id, author_id, text = exc_sql("select id, author_id,
text from review where id=%s", id)
return Review(id, author_id, text)
94.
def cache(key_pattern, expire=0):
def deco(f):
arg_names, varargs, varkw, defaults = inspect.getargspec(f)
if varargs or varkw:
raise Exception("not support varargs")
gen_key = gen_key_factory(key_pattern, arg_names, defaults)
def _(*a, **kw):
key = gen_key(*a, **kw)
r = mc.get(key)
if r is None:
r = f(*a, **kw)
mc.set(key, r, expire)
return r
return _
return deco
95.
def cache(key_pattern, expire=0):
def deco(f):
arg_names, varargs, varkw, defaults = inspect.getargspec(f)
if varargs or varkw:
raise Exception("not support varargs")
gen_key = gen_key_factory(key_pattern, arg_names, defaults)
def _(*a, **kw):
key = gen_key(*a, **kw)
r = mc.get(key)
if r is None:
r = f(*a, **kw)
mc.set(key, r, expire)
return r
return _
return deco
96.
def cache(key_pattern, expire=0):
def deco(f):
arg_names, varargs, varkw, defaults = inspect.getargspec(f)
if varargs or varkw:
raise Exception("not support varargs")
gen_key = gen_key_factory(key_pattern, arg_names, defaults)
def _(*a, **kw):
key = gen_key(*a, **kw)
r = mc.get(key)
if r is None:
r = f(*a, **kw)
mc.set(key, r, expire)
return r
return _
return deco