日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

wsgi初探

發布時間:2025/7/25 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 wsgi初探 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

FROM: http://linluxiang.iteye.com/blog/799163


wsgi初探
前言

本文不涉及WSGI的具體協議的介紹,也不會有協議完整的實現,甚至描述中還會摻雜著本人自己對于WSGI的見解。所有的WSGI官方定義請看http://www.python.org/dev/peps/pep-3333/。


WSGI是什么?

WSGI的官方定義是,the Python Web Server Gateway Interface。從名字就可以看出來,這東西是一個Gateway,也就是網關。網關的作用就是在協議之間進行轉換。



也就是說,WSGI就像是一座橋梁,一邊連著web服務器,另一邊連著用戶的應用。但是呢,這個橋的功能很弱,有時候還需要別的橋來幫忙才能進行處理。



下面對本文出現的一些名詞做定義。 wsgi app ,又稱 應用 ,就是一個WSGI application。 wsgi container ,又稱 容器 ,雖然這個部分常常被稱為handler,不過我個人認為handler容易和app混淆,所以我稱之為容器。 wsgi_middleware ,又稱 中間件 。一種特殊類型的程序,專門負責在容器和應用之間干壞事的。



一圖勝千言,直接來一個我自己理解的WSGI架構圖吧。



可以看出,服務器,容器和應用之間存在著十分糾結的關系。下面就要把這些糾結的關系理清楚。


WSGI應用


WSGI應用其實就是一個callable的對象。舉一個最簡單的例子,假設存在如下的一個應用:


Python代碼 ?
  • def?application(environ,?start_response):??
  • ??status?=?'200?OK'??
  • ??output?=?'World!'??
  • ??response_headers?=?[('Content-type',?'text/plain'),??
  • ??????????????????????('Content-Length',?str(12)]??
  • ??write?=?start_response(status,?response_headers)??
  • ??write('Hello?')??
  • ??return?[output]??



  • 這個WSGI應用簡單的可以用簡陋來形容,但是他的確是一個功能完整的WSGI應用。只不過給人留下了太多的疑點,environ是什么?start_response是什么?為什么可以同時用write和return來返回內容?



    對于這些疑問,不妨自己猜測一下他的作用。聯想到CGI,那么environ可能就是一系列的環境變量,用來表示HTTP請求的信息,比如說method之類的。start_response,可能是接受HTTP response頭信息,然后返回一個write函數,這個write函數可以把HTTP response的body返回給客戶端。return自然是將HTTP response的body信息返回。不過這里的write和函數返回有什么區別?會不會是其實外圍默認調用write對應用返回值進行處理?而且為什么應用的返回值是一個列表呢?說明肯定存在一個對應用執行結果的迭代輸出過程。難道說他隱含的支持iterator或者generator嗎?



    等等,應用執行結果?一個應用既然是一個函數,說明肯定有一個對象去執行它,并且可以猜到,這個對象把environ和start_response傳給應用,將應用的返回結果輸出給客戶端。那么這個對象是什么呢?自然就是WSGI容器了。


    WSGI容器


    先說說WSGI容器的來源,其實這是我自己編造出來的一個概念。來源就是JavaServlet容器。我個人理解兩者有相似的地方,就順手拿過來用了。



    WSGI容器的作用,就是構建一個讓WSGI應用成功執行的環境。成功執行,意味著需要傳入正確的參數,以及正確處理返回的結果,還得把結果返回給客戶端。



    所以,WSGI容器的工作流程大致就是,用webserver規定的通信方式,能從webserver獲得正確的request信息,封裝好,傳給WSGI應用執行,正確的返回response。



    一般來說,WSGI容器必須依附于現有的webserver的技術才能實現,比如說CGI,FastCGI,或者是embed的模式。



    下面利用CGI的方式編寫一個最簡單的WSGI容器。關于WSGI容器的協議官方文檔并沒有具體的說如何實現,只是介紹了一些需要約束的東西。具體內容看PEP3333中的協議。


    Python代碼 ?
  • #!/usr/bin/python??
  • #encoding:utf8??
  • ??
  • import?cgi??
  • import?cgitb??
  • import?sys??
  • import?os??
  • ??
  • #Make?the?environ?argument??
  • environ?=?{}??
  • environ['REQUEST_METHOD']?=?os.environ['REQUEST_METHOD']??
  • environ['SCRIPT_NAME']?=?os.environ['SCRIPT_NAME']??
  • environ['PATH_INFO']?=?os.environ['PATH_INFO']??
  • environ['QUERY_STRING']?=?os.environ['QUERY_STRING']??
  • environ['CONTENT_TYPE']?=?os.environ['CONTENT_TYPE']??
  • environ['CONTENT_LENGTH']?=?os.environ['CONTENT_LENGTH']??
  • environ['SERVER_NAME']?=?os.environ['SERVER_NAME']??
  • environ['SERVER_PORT']?=?os.environ['SERVER_PORT']??
  • environ['SERVER_PROTOCOL']?=?os.environ['SERVER_PROTOCOL']??
  • environ['wsgi.version']?=?(1,?0)??
  • environ['wsgi.url_scheme']?=?'http'??
  • environ['wsgi.input']????????=?sys.stdin??
  • environ['wsgi.errors']???????=?sys.stderr??
  • environ['wsgi.multithread']??=?False??
  • environ['wsgi.multiprocess']?=?True??
  • environ['wsgi.run_once']?????=?True??
  • ??
  • ??
  • #make?the?start_response?argument??
  • #注意,WSGI協議規定,如果沒有body內容,是不能返回http?response頭信息的。??
  • sent_header?=?False??
  • res_status?=?None??
  • res_headers?=?None??
  • ??
  • def?write(body):??
  • ????global?sent_header??
  • ????if?sent_header:??
  • ????????sys.stdout.write(body)??
  • ????else:??
  • ????????print?res_status??
  • ????????for?k,?v?in?res_headers:??
  • ????????????print?k?+?':?'?+?v??
  • ????????print???
  • ????????sys.stdout.write(body)??
  • ????????sent_header?=?True??
  • ??
  • def?start_response(status,?response_headers):??
  • ????global?res_status??
  • ????global?res_headers??
  • ????res_status?=?status??
  • ????res_headers?=?response_headers??
  • ????return?write??
  • ??
  • #here?is?the?application??
  • ??def?application(environ,?start_response):??
  • ????status?=?'200?OK'??
  • ????output?=?'World!'??
  • ????response_headers?=?[('Content-type',?'text/plain'),??
  • ????????????????????????('Content-Length',?str(12)]??
  • ????write?=?start_response(status,?response_headers)??
  • ????write('Hello?')??
  • ????return?[output]??
  • ??
  • #here?run?the?application??
  • result?=?application(environ,?start_response)??
  • for?value?in?result:???
  • ????write(value)??



  • 看吧。其實實現一個WSGI容器也不難。



    不過我從WSGI容器的設計中可以看出WSGI的應用設計上面存在著一個重大的問題就是:為什么要提供兩種方式返回數據?明明只有一個write函數,卻既可以在application里面調用,又可以在容器中傳輸應用的返回值來調用。如果說讓我來設計的話,直接把start_response給去掉了。就用application(environ)這個接口。傳一個方法,然后返回值就是status, response_headers和一個字符串的列表。實際傳輸的方法全部隱藏了。用戶只需要從environ中讀取數據處理就行了。。



    可喜的是,搜了一下貌似web3的標準里面應用的設計和我的想法類似。希望web3協議能早日普及。


    Middleware中間件


    中間件是一類特殊的程序,可以在容器和應用之間干一些壞事。。其實熟悉python的decorator的人就會發現,這和decoraotr沒什么區別。



    下面來實現一個route的簡單middleware。

    Python代碼 ?
  • class?Router(object):??
  • ????def?__init__(self):??
  • ????????self.path_info?=?{}??
  • ????def?route(self,?environ,?start_response):??
  • ????????application?=?self.path_info[environ['PATH_INFO']]??
  • ????????return?application(environ,?start_response)??
  • ????def?__call__(self,?path):??
  • ????????def?wrapper(application):??
  • ????????????self.path_info[path]?=?application??
  • ????????return?wrapper??



  • 這就是一個很簡單的路由功能的middleware。將上面那段wsgi容器的代碼里面的應用修改成如下:


    Python代碼 ?
  • router?=?Router()??
  • ??
  • #here?is?the?application??
  • @router('/hello')??
  • def?hello(environ,?start_response):??
  • ????status?=?'200?OK'??
  • ????output?=?'Hello'??
  • ????response_headers?=?[('Content-type',?'text/plain'),??
  • ????????????????????????('Content-Length',?str(len(output)))]??
  • ????write?=?start_response(status,?response_headers)??
  • ????return?[output]??
  • ?
  • @router('/world')??
  • def?world(environ,?start_response):??
  • ????status?=?'200?OK'??
  • ????output?=?'World!'??
  • ????response_headers?=?[('Content-type',?'text/plain'),??
  • ????????????????????????('Content-Length',?str(len(output)))]??
  • ????write?=?start_response(status,?response_headers)??
  • ????return?[output]??
  • #here?run?the?application??
  • result?=?router.route(environ,?start_response)??
  • for?value?in?result:???
  • ????write(value)??



  • 這樣,容器就會自動的根據訪問的地址找到對應的app執行了。


    延伸


    寫著寫著,怎么越來越像一個框架了?看來Python開發框架真是簡單。。



    其實從另外一個角度去考慮。如果把application當作是一個運算單元。利用middleware調控IO和運算資源,那么利用WSGI組成一個分布式的系統。

    總結

    以上是生活随笔為你收集整理的wsgi初探的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。