自己動(dòng)手寫(xiě)一個(gè)web框架,因?yàn)槲沂遣锁B(niǎo),對(duì)于python的一些內(nèi)建函數(shù)不是清楚,所以在寫(xiě)這篇文章之前需要一些python和WSGI的預(yù)備知識(shí),這是一系列文章。這一篇只實(shí)現(xiàn)了如何處理url。
參考這篇文章:http://m.survivalescaperooms.com/russellluo/p/3338616.html
web框架主要是實(shí)現(xiàn)web服務(wù)器和web應(yīng)用之間的交互。底層的網(wǎng)絡(luò)協(xié)議主要有web服務(wù)器完成。譬如監(jiān)聽(tīng)端口,填充報(bào)文等等。
迭代器為類序列對(duì)象提供了類序列的接口,也就是說(shuō)類序列對(duì)象可以通過(guò)迭代器像序列一樣進(jìn)行迭代。說(shuō)簡(jiǎn)單一點(diǎn)就是遍歷對(duì)象。如果想讓類是可迭代的,那么就必須實(shí)現(xiàn)__iter__和next()。
只要在類定義的時(shí)候?qū)崿F(xiàn)了__call__方法,那么該類的對(duì)象就是可調(diào)有的,即可以將對(duì)象當(dāng)做函數(shù)來(lái)使用。這里只用明白什么是__call__函數(shù)即可,因?yàn)閃SGI規(guī)范中用要求。
關(guān)于WSGI的介紹可以點(diǎn)擊http://webpython.codepoint.net,有很詳細(xì)的介紹。這里只說(shuō)明一下大概。WSGI接口是用可調(diào)用的對(duì)象實(shí)現(xiàn)的:一個(gè)函數(shù),一個(gè)方法或者一個(gè)可調(diào)用的實(shí)例。下面是一個(gè)實(shí)例,注釋寫(xiě)的很詳細(xì):
# This is our application object. It could have any name,# except when using mod_wsgi where it must be "application"def application( # It accepts two arguments: # environ points to a dictionary containing CGI like environment variables # which is filled by the server for each received request from the client environ, # start_response is a callback function supplied by the server # which will be used to send the HTTP status and headers to the server start_response): # build the response body possibly using the environ dictionary response_body = 'The request method was %s' % environ['REQUEST_METHOD'] # HTTP response code and message status = '200 OK' # These are HTTP headers expected by the client. # They must be wrapped as a list of tupled pairs: # [(Header name, Header value)]. response_headers = [('Content-Type', 'text/plain'), ('Content-Length', str(len(response_body)))] # Send them to the server using the supplied function start_response(status, response_headers) # Return the response body. # Notice it is wrapped in a list although it could be any iterable. return [response_body]
簡(jiǎn)單來(lái)說(shuō)就是根據(jù)接收的參數(shù)來(lái)返回相應(yīng)的結(jié)果。
我之前用過(guò)django寫(xiě)過(guò)一個(gè)很簡(jiǎn)單的博客,目前放在SAE上,好久沒(méi)更新了。網(wǎng)址:http://3.mrzysv5.sinaapp.com。一個(gè)web框架最基本的要求就是簡(jiǎn)化用戶的代碼量。所以在django中,我只需要寫(xiě)view、model和url配置文件。下面是我用django時(shí)寫(xiě)的一個(gè)處理視圖的函數(shù):
def blog_list(request): blogs = Article.objects.all().order_by('-publish_date') blog_num = Article.objects.count() return render_to_response('index.html', {"blogs": blogs,"blog_num":blog_num}, context_instance=RequestContext(request))def blog_detail(request): bid = request.GET.get('id','') blog = Article.objects.get(id=bid) return render_to_response('blog.html',{'blog':blog})需要我完成的就是操作數(shù)據(jù)庫(kù),返回相應(yīng)的資源。所以我要編寫(xiě)的web框架就要盡可能的封裝一些底層操作,留給用戶一些可用的接口。根據(jù)我的觀察,web框架的處理過(guò)程大致如下:
一個(gè)WSGI基類,主要有以下的功能:
import reclass WSGIapp: headers = [] def __init__(self,urls=()): self.urls = urls self.status = '200 OK' def __call__(self,environ,start_response): x = self.mapping_urls(environ) PRint x start_response(self.status,self.headers) if isinstance(x,str): return iter([x]) else: return iter(x) def mapping_urls(self,environ): path = environ['PATH_INFO'] for pattern,name in self.urls: m = re.match('^'+pattern+'$',path) if m: args = m.groups() func = globals()[name] return func(*args) return self.notfound() def notfound(self): self.status = '404 Not Found' self.headers = [('Content-Type','text/plain')] return '404 Not Found/n' @classmethod def header(cls,name,value): cls.headers.append((name,value))def GET_index(*args): WSGIapp.header('Content-Type','text/plain') return 'Welcome!/n'def GET_hello(*args): WSGIapp.header('Content-Type','text/plain') return 'Hello %s!/n' % argsurls = [ ('/','GET_index'), ('/hello/(.*)','GET_hello') ]wsgiapp = WSGIapp(urls)if __name__ == '__main__': from wsgiref.simple_server import make_server httpd = make_server('',8000,wsgiapp) print 'server starting...' httpd.serve_forever()
上面的代碼是不是很簡(jiǎn)介了,只需要定義函數(shù)即可。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注