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實作兩個功能
- 執行使用者函數并傳回結果
- 實作路由對應分發