• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Python于Web 2.0网站的应用 - QCon Beijing 2010
 

Python于Web 2.0网站的应用 - QCon Beijing 2010

on

  • 49,165 views

在QCon Beijing 2010上的演讲

在QCon Beijing 2010上的演讲

Statistics

Views

Total Views
49,165
Views on SlideShare
44,215
Embed Views
4,950

Actions

Likes
327
Downloads
2,999
Comments
20

54 Embeds 4,950

http://www.it168.com 2321
http://www.slideshare.net 522
http://www.shaoqi.net 318
http://www.pythoner.info 312
http://newliver.yo2lua.com 238
http://www.cnblogs.com 222
http://www.lifeyun.com 171
http://www.beijing-open-party.org 168
http://sunxiunan.com 155
http://app.beijing-open-party.org 127
http://www.mypython.info 85
http://localhost 69
http://blog.chinaunix.net 26
http://10.150.200.57 26
http://ziso.me 24
http://yanng.cnblogs.com 23
http://www.am82.com 22
http://meng-han.blogspot.com 21
http://baygle.us 17
http://cache.baidu.com 9
http://static.slidesharecdn.com 9
http://xianguo.com 8
http://blogold.chinaunix.net 6
http://kiss-emacs.blogspot.com 5
http://127.0.0.1:5000 5
http://skylai-asone.blogspot.com 3
http://it.aooooo.com 3
http://livebuzz.com.br 2
http://localhost:8000 2
http://www.linxun.info 2
http://wiki.umlife.net 2
http://pythonspace.webfactional.com 2
http://www.taaza.com 2
http://www.cublog.cn 2
http://www.baygle.us 2
http://kiss-emacs.blogspot.de 1
http://192.168.245.161 1
http://meng-han.blogspot.jp 1
http://kiss-emacs.blogspot.tw 1
http://kiss-emacs.blogspot.com.br 1
http://meng-han.blogspot.co.uk 1
https://unminiluv.appspot.com 1
http://start.knox.nsw.edu.au 1
http://twitter.com 1
http://findlettoo.appspot.com 1
http://webcache.googleusercontent.com 1
http://facebook.slideshare.com 1
https://webcache.googleusercontent.com 1
http://s.deeeki.com 1
http://www.zhuaxia.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-ShareAlike LicenseCC Attribution-ShareAlike License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

110 of 20 previous next Post a comment

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • 牛~~
    Are you sure you want to
    Your message goes here
    Processing…
  • learn python~!
    Are you sure you want to
    Your message goes here
    Processing…
  • Great slides. Thanks for sharing.

    Regards
    http://www.clickandsendparcel.com
    Are you sure you want to
    Your message goes here
    Processing…
  • 豆瓣
    Are you sure you want to
    Your message goes here
    Processing…
  • 没有声音?
    Are you sure you want to
    Your message goes here
    Processing…

110 of 20 previous next

Post Comment
Edit your comment

    Python于Web 2.0网站的应用 - QCon Beijing 2010 Python于Web 2.0网站的应用 - QCon Beijing 2010 Presentation Transcript

    • Python Web 2.0 QCon Beijing 2010 http://www.flickr.com/photos/arnolouise/2986467632/
    • About Me • Python • 2002 Python • 2004 Python • http://www.douban.com/ people/hongqn/ • hongqn@douban.com • http://twitter.com/hongqn
    • 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/)
    • Languages in C 27% Javascript 12% C++ Python 3% 58% (Pyrex/R/Erlang/Go/Shell) 1%
    • Why Python?
    • • Hello World: 1
    • • Hello World: 1 • :1
    • • Hello World: 1 • :1 • :1
    • • Hello World: 1 • :1 • :1 • :3
    • : 13
    • : 13 import os from collections 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
    • • • Pythonic
    • • 1. svn ci 2. svn up 3. restart
    • • Web • • •
    • • Battery Included: 200+ • PyPI: 9613 packages currently • / / / / / / /... • easily extensible
    • Python
    • Python
    • Python Just kidding :-p
    • Web Server
    • Web Server • python -m SimpleHTTPServer
    • Web Server • python -m SimpleHTTPServer
    • web.py http://webpy.org/ import web urls = ( '/(.*)', 'hello' ) app = web.application(urls, globals()) class hello: def GET(self, name): if not name: name = 'World' return 'Hello, ' + name + '!' if __name__ == "__main__": app.run()
    • Flask http://flask.pocoo.org/ import flask import Flask app = Flask(__name__) @app.route("/<name>") def hello(name): if not name: name = 'World' return 'Hello, ' + name + '!' if __name__ == "__main__": app.run()
    • WSGI http://www.python.org/dev/peps/pep-0333/
    • Why so many Python 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
    • doctest def cube(x): """ >>> cube(10) 1000 """ return x * x def _test(): import doctest doctest.testmod() if __name__ == "__main__": _test()
    • nose http://somethingaboutorange.com/mrl/projects/nose/ from cube import cube def test_cube(): result = cube(10) assert result == 1000
    • 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]])
    • 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)
    • 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)
    • virtualenv http://virtualenv.openplans.org/ python $ python go-pylons.py --no-site-packages mydevenv $ cd mydevenv $ source bin/activate (mydevenv)$ paster create -t new9 helloworld
    • Pyrex/Cython cdef extern from "math.h" double sin(double) cdef double f(double x): return sin(x*x)
    • Pythonic
    • >>> import this The Zen 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.  
    • In the face of 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!
    • Simple is better than complex class HelloWorld { public static void main(String args[]) { System.out.println("Hello World!"); } }
    • Simple is better than complex print "Hello World!"
    • Readability counts
    • Readability counts • {} end
    • Readability counts • {} end • (except "@" for decorators)
    • Readability counts • {} end • (except "@" for decorators) if limit is not None and len(ids)>limit: ids = random.sample(ids, limit)
    • TOOWTDI • There (should be) Only One Way To Do It. • vs. Perlish TIMTOWTDI (There Is More Than One Way To Do It)
    • 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)
    • 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)
    • 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)
    • 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)
    • TOOWTDI • There (should be) 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]
    • http://twitter.com/robbinfan/status/9879724095 http://twitter.com/hongqn/status/9883515681
    • Python C http://www.flickr.com/photos/nicksieger/281055485/ http://www.flickr.com/photos/nicksieger/281055530/
    • Ruby http://www.flickr.com/photos/nicksieger/280661836/
    • Java http://www.flickr.com/photos/nicksieger/280662707/
    • Python
    • • svn
    • • svn • ( list)
    • • svn • ( list) • +
    • • svn • ( list) • + • parser
    • config.py MEMCACHED_ADDR = ['localhost:11211'] from local_config import *
    • config.py MEMCACHED_ADDR = ['localhost:11211'] from local_config import * local_config.py MEMCACHED_ADDR = [ 'frodo:11211', 'sam:11211', 'pippin:11211', 'merry:11211', ]
    • config.py MEMCACHED_ADDR = ['localhost:11211'] from local_config import * .py local_config.py exec MEMCACHED_ADDR = [ 'frodo:11211', 'sam:11211', 'pippin:11211', 'merry:11211', ]
    • class GroupUI(object): def new_topic(self, request): if self.group.can_post(request.user): return new_topic_ui(self.group) else: request.response.set_status(403, "Forbidden") return error_403_ui(msg=" ") def join(self, request): if self.group.can_join(request.user): ... class Group(object): def can_post(self, user): return self.group.has_member(user) def can_join(self, user): return not self.group.has_banned(user)
    • class GroupUI(object): @check_permission('post', msg=" ") def new_topic(self, request): return new_topic_ui(self.group) @check_permission('join', msg=" ") def join(self, request): ... class Group(object): def can_post(self, user): return self.group.has_member(user) def can_join(self, user): return not self.group.has_banned(user)
    • decorator def print_before_exec(func): def _(*args, **kwargs): print "decorated" return func(*args, **kwargs) return _ @print_before_exec def double(x): print x*2 double(10)
    • decorator def print_before_exec(func): def _(*args, **kwargs): print "decorated" return func(*args, **kwargs) return _ decorated @print_before_exec def double(x): 20 print x*2 double(10)
    • class check_permission(object): def __init__(self, action, msg=None): self.action = action self.msg = msg def __call__(self, func): def _(ui, req, *args, **kwargs): f = getattr(ui.perm_obj, 'can_' + self.action) if f(req.user): return func(ui, *args, **kwargs) raise BadPermission(ui.perm_obj, self.action, self.msg) return _
    • class check_permission(object): def __init__(self, action, msg=None): self.action = action self.msg = msg def __call__(self, func): def _(ui, req, *args, **kwargs): f = getattr(ui.perm_obj, 'can_' + self.action) if f(req.user): return func(ui, *args, **kwargs) raise BadPermission(ui.perm_obj, self.action, self.msg) return _
    • class check_permission(object): def __init__(self, action, msg=None): self.action = action self.msg = msg def __call__(self, func): def _(ui, req, *args, **kwargs): f = getattr(ui.perm_obj, 'can_' + self.action) if f(req.user): return func(ui, *args, **kwargs) raise BadPermission(ui.perm_obj, self.action, self.msg) return _
    • class check_permission(object): def __init__(self, action, msg=None): self.action = action self.msg = msg def __call__(self, func): def _(ui, req, *args, **kwargs): f = getattr(ui.perm_obj, 'can_' + self.action) if f(req.user): return func(ui, *args, **kwargs) raise BadPermission(ui.perm_obj, self.action, self.msg) return _
    • class check_permission(object): def __init__(self, action, msg=None): self.action = action self.msg = msg def __call__(self, func): def _(ui, req, *args, **kwargs): f = getattr(ui.perm_obj, 'can_' + self.action) if f(req.user): return func(ui, *args, **kwargs) raise BadPermission(ui.perm_obj, self.action, self.msg) return _
    • class check_permission(object): def __init__(self, action, msg=None): self.action = action self.msg = msg def __call__(self, func): def _(ui, req, *args, **kwargs): f = getattr(ui.perm_obj, 'can_' + self.action) if f(req.user): return func(ui, *args, **kwargs) raise BadPermission(ui.perm_obj, self.action, self.msg) return _
    • class GroupUI(object): @check_permission('post', msg=" ") def new_topic(self, request): return new_topic_ui(self.group) @check_permission('join', msg=" ") def join(self, request): ... class Group(object): def can_post(self, user): return self.group.has_member(user) def can_join(self, user): return not self.group.has_banned(user)
    • def send_notification_mail(email, subject, body): msg = MSG_SEND_MAIL + '0' + email + '0' + subject + '0' + body mq.put(msg) def async_worker(): msg = mq.get() msg = msg.split('0') cmd = msg[0] if cmd == MSG_SEND_MAIL: email, subject, body = msg[1:] fromaddr = 'no-reply@douban.com' email_body = make_email_body(fromaddr, email, subject, body) smtp = smtplib.SMTP('mail') smtp.sendmail(fromaddr, email, email_body) elif cmd == MSG_xxxx: ... elif cmd == MSG_yyyy: ...
    • @async def send_notification_mail(email, subject, body): fromaddr = 'no-reply@douban.com' email_body = make_email_body(fromaddr, email, subject, body) smtp = smtplib.SMTP('mail') smtp.sendmail(fromaddr, email, email_body)
    • def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__ mod.__dict__[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod.__dict__[fname](*a, **kw)
    • def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__ mod.__dict__[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod.__dict__[fname](*a, **kw)
    • def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__ mod.__dict__[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod.__dict__[fname](*a, **kw)
    • def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__ mod.__dict__[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod.__dict__[fname](*a, **kw)
    • def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__ mod.__dict__[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod.__dict__[fname](*a, **kw)
    • def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__ mod.__dict__[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod.__dict__[fname](*a, **kw)
    • def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__ mod.__dict__[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod.__dict__[fname](*a, **kw)
    • def async(func): mod = sys.modules[func.__module__] fname = 'origin_' + func.__name__ mod.__dict__[fname] = func def _(*a, **kw): body = cPickle.dumps((mod.__name__, fname, a, kw)) mq.put(body) return _ def async_worker(): modname, fname, a, kw = cPickle.loads(mq.get()) __import__(modname) mod = sys.modules[modname] mod.__dict__[fname](*a, **kw)
    • • cache (SQL, , etc)
    • def get_latest_review_id(): review_id = mc.get('latest_review_id') if review_id is None: review_id = exc_sql("select max(id) from review") mc.set('latest_review_id', review_id) return review_id
    • @cache('latest_review_id') def get_latest_review_id(): return exc_sql("select max(id) from review")
    • 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
    • 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
    • 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
    • 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)
    • 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
    • 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
    • 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
    • inspect.getargspec >>> import inspect >>> def f(a, b=1, c=2): ... pass ... >>> inspect.getargspec(f) ArgSpec(args=['a', 'b', 'c'], varargs=None, keywords=None, defaults=(1, 2)) >>> >>> >>> def f(a, b=1, c=2, *args, **kwargs): ... pass ... >>> inspect.getargspec(f) ArgSpec(args=['a', 'b', 'c'], varargs='args', keywords='kwargs', defaults=(1, 2))
    • 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
    • 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: hint: r = f(*a, **kw) mc.set(key, r, expire) return r • str.format in python 2.6: '{id}'.format(id=1) => '1' return _ return deco • dict(zip(['a', 'b', 'c'], [1, 2, 3])) => {'a': 1, 'b': 2, 'c': 3}
    • 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: hint: r = f(*a, **kw) mc.set(key, r, expire) return r • str.format in python 2.6: '{id}'.format(id=1) => '1' return _ return deco • dict(zip(['a', 'b', 'c'], [1, 2, 3])) => {'a': 1, 'b': 2, 'c': 3}
    • 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
    • • feed feed entry_id
    • class Feed(object): def get_entries(self, limit=10): ids = exc_sqls("select id from entry where feed_id= %s order by id desc limit %s", (self.id, limit)) return [Entry.get(id) for id in ids] class FeedCollection(object): def get_entries(self, limit=10): mixed_entries = [] for feed in self.feeds: entries = feed.get_entries(limit=limit) mixed_entries += entries mixed_entries.sort(key=lambda e: e.id, reverse=True) return mixed_entries[:10]
    • class Feed(object): def get_entries(self, limit=10): ids = exc_sqls("select id from entry where feed_id= %s order by id desc limit %s", (self.id, limit)) return [Entry.get(id) for id in ids] class FeedCollection(object): def get_entries(self, limit=10): mixed_entries = [] for feed in self.feeds: entries = feed.get_entries(limit=limit) mixed_entries += entries mixed_entries.sort(key=lambda e: e.id, reverse=True) return mixed_entries[:10]
    • class Feed(object): def get_entries(self, limit=10): ids = exc_sqls("select id from entry where feed_id= %s order by id desc limit %s", (self.id, limit)) return [Entry.get(id) for id in ids] class FeedCollection(object): def get_entries(self, limit=10): mixed_entries = [] for feed in self.feeds: entries = feed.get_entries(limit=limit) mixed_entries += entries mixed_entries.sort(key=lambda e: e.id, reverse=True) return mixed_entries[:10]
    • class Feed(object): def get_entries(self, limit=10): ids = exc_sqls("select id from entry where feed_id= %s order by id desc limit %s", (self.id, limit)) return [Entry.get(id) for id in ids] class FeedCollection(object): = def get_entries(self, limit=10): len(self.feeds) * limit mixed_entries = [] for feed in self.feeds: entries = feed.get_entries(limit=limit) mixed_entries += entries mixed_entries.sort(key=lambda e: e.id, reverse=True) return mixed_entries[:10]
    • class Feed(object): def get_entries(self, limit=10): ids = exc_sqls("select id from entry where feed_id= %s order by id desc limit %s", (self.id, limit)) return [Entry.get(id) for id in ids] class FeedCollection(object): Entry.get = def get_entries(self, limit=10): len(self.feeds-1) * limit mixed_entries = [] for feed in self.feeds: entries = feed.get_entries(limit=limit) mixed_entries += entries mixed_entries.sort(key=lambda e: e.id, reverse=True) return mixed_entries[:10]
    • iterator and generator def fib(): x, y = 1, 1 while True: yield x x, y = y, x+y def odd(seq): return (n for n in seq if n%2) def less_than(seq, upper_limit): for number in seq: if number >= upper_limit: break yield number print sum(odd(less_than(fib(), 4000000)))
    • itertools • count([n]) --> n, n+1, n+2 • cycle(p) --> p0, p1, ... plast, p0, p1, ... • repeat(elem [,n]) --> elem, elem, elem, ... endless or up to n times • izip(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... • islice(seq, [start,] stop [, step]) --> elements from seq[start:stop:step] • ... and more ...
    • class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: yield Entry.get(entry_id) start_id = entry_ids[-1] class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit))
    • class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: yield Entry.get(entry_id) start_id = entry_ids[-1] class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit))
    • class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: yield Entry.get(entry_id) start_id = entry_ids[-1] class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit))
    • class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: yield Entry.get(entry_id) start_id = entry_ids[-1] class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit))
    • class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: yield Entry.get(entry_id) start_id = entry_ids[-1] class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit))
    • class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: = yield Entry.get(entry_id) len(self.feeds) * 5 ~ start_id = entry_ids[-1] len(self.feeds)*5 + limit -5 class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit))
    • class Feed(object): def iter_entries(self): start_id = sys.maxint while True: entry_ids = exc_sqls("select id from entry where feed_id=%s and id<%s order by id desc limit 5", (self.id, start_id)) if not entry_ids: break for entry_id in entry_ids: yield Entry.get(entry_id) start_id = entry_ids[-1] Entry.get = 0 ~ len(self.feeds)-1 class FeedCollection(object): def iter_entries(self): return imerge(*[feed.iter_entries() for feed in self.feeds]) def get_entries(self, limit=10): return list(islice(self.iter_entries(), limit))
    • decorator generator
    • class User(object): def __init__(self, id, username, screen_name, sig): self.id = id self.username = username self.screen_name = screen_name self.sig = sig user = User('1002211', 'hongqn', 'hongqn', " ")
    • cPickle vs. marshal $ python -m timeit -s ' > from user import user > from cPickle import dumps, loads > s = dumps(user, 2)' > 'loads(s)' 100000 loops, best of 3: 6.6 usec per loop $ python -m timeit -s ' > from user import user > from marshal import dumps, loads > d = (user.id, user.username, user.screen_name, user.sig) > s = dumps(d, 2)' 'loads(s)' 1000000 loops, best of 3: 0.9 usec per loop
    • cPickle vs. marshal $ python -m timeit -s ' > from user import user > from cPickle import dumps, loads > s = dumps(user, 2)' > 'loads(s)' 7 100000 loops, best of 3: 6.6 usec per loop $ python -m timeit -s ' > from user import user > from marshal import dumps, loads > d = (user.id, user.username, user.screen_name, user.sig) > s = dumps(d, 2)' 'loads(s)' 1000000 loops, best of 3: 0.9 usec per loop
    • cPickle vs. marshal $ python -m timeit -s ' > from user import user > from cPickle import dumps, loads > s = dumps(user, 2)' > 'loads(s)' 7 100000 loops, best of 3: 6.6 usec per loop $ python -m timeit -s ' > from user import user > from marshal import dumps, loads > d = (user.id, user.username, user.screen_name, user.sig) > s = dumps(d, 2)' 'loads(s)' 1000000 loops, best of 3: 0.9 usec per loop
    • cPickle vs. marshal $ python -c timeit ' > import cPickle, marshal > from user import user > print "pickle:", len(cPickle.dumps(user, 2)) > print "marshal:", len(marshal.dumps((user.id, > user.username, user.screen_name, user.sig), 2))' pickle: 129 marshal: 74 43%
    • cPickle vs. marshal $ python -c timeit ' > import cPickle, marshal > from user import user > print "pickle:", len(cPickle.dumps(user, 2)) > print "marshal:", len(marshal.dumps((user.id, > user.username, user.screen_name, user.sig), 2))' pickle: 129 marshal: 74 43%
    • namedtuple from collections import namedtuple User = namedtuple('User', 'id username screen_name sig') user = User('1002211', 'hongqn', 'hongqn', sig=" ") user.username -> 'hongqn'
    • __metaclass__ class User(tuple): __metaclass__ = NamedTupleMetaClass __attrs__ = ['id', 'username', 'screen_name', 'sig'] user = User('1002211', 'hongqn', 'hongqn', sig=" ") s = marshal.dumps(user.__marshal__()) User.__load_marshal__(marshal.loads(s))
    • from operator import itemgetter class NamedTupleMetaClass(type): def __new__(mcs, name, bases, dict): assert bases == (tuple,) for i, a in enumerate(dict['__attrs__']): dict[a] = property(itemgetter(i)) dict['__slots__'] = () dict['__marshal__'] = tuple dict['__load_marshal__'] = classmethod(tuple.__new__) dict['__getnewargs__'] = lambda self: tuple(self) argtxt = repr(tuple(attrs)).replace("'", "")[1:-1] template = """def newfunc(cls, %(argtxt)s): return tuple.__new__(cls, (%(argtxt)s))""" % locals() namespace = {} exec template in namespace dict['__new__'] = namespace['newfunc'] return type.__new__(mcs, name, bases, dict)
    • Warning!
    • • request.get_environ(key) • e.g. request.get_environ('REMOTE_ADDR') --> request.remote_addr
    • descriptor • __get__, __set__ __delete__ class Descriptor(object): def __get__(self, instance, owner): return 'descriptor' class Owner(object): attr = Descriptor() owner = Owner() owner.attr --> 'descriptor'
    • descriptor • classmethod • staticmethod • property class C(object): def get_x(self): return self._x def set_x(self, x): self._x = x x = property(get_x, set_x)
    • class environ_getter(object): def __init__(self, key, default=None): self.key = key self.default = default def __get__(self, obj, objtype): if obj is None: return self return obj.get_environ(self.key, self.default) class HTTPRequest(quixote.http_request.HTTPRequest): for key in ['HTTP_REFERER', 'REMOTE_ADDR', 'SERVER_NAME', 'REQUEST_URI', 'HTTP_HOST']: locals()[key.lower()] = environ_getter(key) locals() del key
    • class environ_getter(object): def __init__(self, key, default=None): self.key = key self.default = default def __get__(self, obj, objtype): if obj is None: return self return obj.get_environ(self.key, self.default) class HTTPRequest(quixote.http_request.HTTPRequest): for key in ['HTTP_REFERER', 'REMOTE_ADDR', 'SERVER_NAME', 'REQUEST_URI', 'HTTP_HOST']: locals()[key.lower()] = environ_getter(key) del key
    • • urllib.urlopen socks
    • Monkey Patch
    • import httplib orig_connect = httplib.HTTPConnection.connect def _patched_connect(self): if HOSTS_BLOCKED.match(self.host): return _connect_via_socks_proxy(self) else: return orig_connect(self) def _connect_via_socks_proxy(self): ... httplib.HTTPConnection.connect = _patched_connect
    • Python
    • Python • Pythonic!
    • Python • Pythonic! • Avoid gotchas http://www.ferg.org/projects/python_gotchas.html
    • Python • Pythonic! • Avoid gotchashttp://www.ferg.org/projects/python_gotchas.html • Unicode / Character Encoding
    • Python • Pythonic! • Avoid gotchas http://www.ferg.org/projects/python_gotchas.html • Unicode / Character Encoding • GIL (Global Interpreter Lock)
    • Python • Pythonic! • Avoid gotchas http://www.ferg.org/projects/python_gotchas.html • Unicode / Character Encoding • GIL (Global Interpreter Lock) • Garbage Collection
    • • :Vim / Emacs / Ulipad • : subversion / mercurial / git • wiki/ / : Trac • : Bitten
    • Python Implementations
    • Python Implementations • CPython http://www.python.org/
    • Python Implementations • CPython http://www.python.org/ • Unlanden-Swallow http://code.google.com/p/unladen-swallow/
    • Python Implementations • CPython http://www.python.org/ • Unlanden-Swallow http://code.google.com/p/unladen-swallow/ • Stackless Python http://www.stackless.com/
    • Python Implementations • CPython http://www.python.org/ • Unlanden-Swallow http://code.google.com/p/unladen-swallow/ • Stackless Python http://www.stackless.com/ • IronPython http://ironpython.net/
    • Python Implementations • CPython http://www.python.org/ • Unlanden-Swallow http://code.google.com/p/unladen-swallow/ • Stackless Python http://www.stackless.com/ • IronPython http://ironpython.net/ • Jython http://www.jython.org/
    • Python Implementations • CPython http://www.python.org/ • Unlanden-Swallow http://code.google.com/p/unladen-swallow/ • Stackless Python http://www.stackless.com/ • IronPython http://ironpython.net/ • Jython http://www.jython.org/ • PyPy http://pypy.org/
    • Q &A