from klein import run, route
@route('/')
def home(request):
return 'Hello, world!'
run("localhost", 8080)
首先进入其Klein.route
#route是Kelin类下的一个方法
route = _globalKleinApp.route
_globalKleinApp = Klein()
def route(self, url, *args, **kwargs):
"""
Add a new handler for C{url} passing C{args} and C{kwargs} directly to
C{werkzeug.routing.Rule}. The handler function will be passed at least
one argument an L{twisted.web.server.Request} and any keyword arguments
taken from the C{url} pattern.
::
@app.route("/")
def index(request):
return "Hello"
@param url: A werkzeug URL pattern given to C{werkzeug.routing.Rule}.
@type url: str
@param branch: A bool indiciated if a branch endpoint should
be added that allows all child path segments that don't
match some other route to be consumed. Default C{False}.
@type branch: bool
@returns: decorated handler function.
"""
#用户的URL和基本URL一共几个'/'
segment_count = self._segments_in_url(url) + self._subroute_segments
#装饰器,返回deco
@named("router for '" + url + "'")
def deco(f):
kwargs.setdefault('endpoint', f.__name__) #在kwargs里设置键值对endpoint为函数名字
if kwargs.pop('branch', False): #如果kwargs里存在‘branch’
branchKwargs = kwargs.copy() #深拷贝,一级目录深拷贝,二级目录浅拷贝(引用,指针)
branchKwargs['endpoint'] = branchKwargs['endpoint'] + '_branch' #将拷贝对象的endpoint加上_branch
@modified("branch route '{url}' executor".format(url=url), f)
def branch_f(instance, request, *a, **kw):
IKleinRequest(request).branch_segments = (
kw.pop('__rest__', '').split('/')
)
return _call(instance, f, request, *a, **kw) #执行函数f(*args, **kwargs) args = (instance,) + args
branch_f.segment_count = segment_count
self._endpoints[branchKwargs['endpoint']] = branch_f#字典保存键值对(函数名字:branch_f)
#路由分发里添加路由
self._url_map.add(
Rule(
url.rstrip('/') + '/' + '<path:__rest__>',#在路由末尾添加'/',确保用户没有添加
*args, **branchKwargs
)
)
@modified("route '{url}' executor".format(url=url), f)
def _f(instance, request, *a, **kw):
#_call就是f执行(*a,**kw)
return _call(instance, f, request, *a, **kw)
_f.segment_count = segment_count
self._endpoints[kwargs['endpoint']] = _f
self._url_map.add(Rule(url, *args, **kwargs))
return f
return deco
是两层嵌套的装饰器函数
segment_count就是计算routr(url)中的url有几个'/'
#这个方法返回一个URL里的'/'数量
@staticmethod
def _segments_in_url(url):
segment_count = url.count('/') #一个URL里有多少个'/'
if url.endswith('/'): #如果URL以'/'结尾,数量-1
segment_count -= 1
return segment_count
@name装饰器是改变函数的__name__和__qualname__为
"router for '" + url + "'"
#name——"router for '" + url + "'"
#original——function
#这个装饰器的作用是:改变函数__name__,和__qualname__,最后返回函数
def named(name):
"""
Change the name of a function to the given name.
"""
def decorator(original):
original.__name__ = str(name)
original.__qualname__ = str(name)
return original
return decorator
@modified装饰器是执行用户的function(branch_f)或者function(f),并返回结果
#modification "branch route '{url}' executor".format(url=url)
#original 也就是用户的function
def modified(modification, original, modifier=None):
#wrapper是 def branch_f(instance, request, *a, **kw)
def decorator(wrapper):
result = (named(modification + ' for ' + original.__name__)
(wraps(original)(wrapper)))#用户function执行_f,request=_f,request就是result = f(*args, **kwargs)
result.__original__ = original
if modifier is not None:
before = set(wrapper.__dict__.keys())
result = modifier(result)
after = set(wrapper.__dict__.keys())
for key in after - before:
setattr(original, key, wrapper.__dict__[key])
return result
return decorator
@modified("route '{url}' executor".format(url=url), f)
def _f(instance, request, *a, **kw):
#_call就是f执行(*a,**kw)
return _call(instance, f, request, *a, **kw)
_f.segment_count = segment_count
self._endpoints[kwargs['endpoint']] = _f
self._url_map.add(Rule(url, *args, **kwargs))
return f
之后实现路由添加
#路由分发里添加路由
self._url_map.add(
Rule(
url.rstrip('/') + '/' + '<path:__rest__>',#在路由末尾添加'/',确保用户没有添加
*args, **branchKwargs
)
)
虽然Klein是twisted实现的,但是route却不是基于twisted,正如同Flask也有route,这只是一种设计哲学,可以学来到处用。
真正用到Twisted的,应该在于run和template,稍后在看吧。
综上分析route实现两个功能
- 执行用户函数并返回结果
- 实现路由对应分发