web學習之wsgi

from wsgiref.simple_server import make_server


def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, web!</h1>']


httpd = make_server('', 8080, application)

print('Serving HTTP on port 8000...')
# 開始監聽HTTP請求:
httpd.serve_forever()
View Code

          學習筆記之WSGI

WSGI是幹嗎用的?爲何存在?html

由於咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口,讓咱們專心用Python編寫Web業務。前端

而這個接口就算WSGI:Web Server Gateway Interface。web

make_server的做用是幫咱們封裝一些操做:
包括socket對象,綁定(bind),監聽(listen)等。後端

便是將以下這些封裝打包:瀏覽器

sk = socket.socket()
 
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)

這樣子咱們就省了一些功夫去作這些基礎性的工做,可是make_server仍是須要ip地址和端口來綁定對象。app

傳入的applicadtion參數不須要本身執行,傳進去的是函數名,在內部會幫你執行。
以後拿到一個make_server實例化對象傳給httpd,再用serve_forever去執行。socket

application的重要參數:
(注意:application是server端,所設置的響應頭和響應體都是給客戶端看的。)ide

  • .start_response: 設置響應頭的參數

  例如:
  start_response('200 OK', [('Content-Type', 'text/html')])
  其字典類型的參數應該放在一個大列表裏面,大列表裏包括鍵值對元祖。
  例如('Content-Type', 'text/html')就至關於傳了 Content-Type = text / html 給客戶端函數

  • environ:封裝http解析的信息的參數。

http解析完的數據都放到了environ這個對象裏面
想取出environ的值能夠經過取出鍵的值,例如你的子路徑是book時能夠
用environ['PATH_INFO']。當你相對客戶輸入不一樣的路徑作出不一樣的響應時,
可也經過if else語句和environ結合來作。學習

def application(environ, start_response):
               start_response('200 OK', [('Content-Type', 'text/html')])
               path = environ['PATH_INFO']
               if path == '/book':
                    return [b'Hello book']
               elif path == '/blog':
                    return [b'Hello web']
               else:
                    return ['<h1>404</h1>'.encode('utf8')]
View Code

優化一下:將客戶端發送不一樣的請求時返回的不一樣的數據這步操做分別寫到不一樣的函數裏邊。

def f1():
                return [b'Hello book']
           def f2():
                return [b'Hello web']
           def application(environ, start_response):
               start_response('200 OK', [('Content-Type', 'text/html')])
               path = environ['PATH_INFO']
               if path == '/book':
                    return f1()
               elif path == '/blog':
                    return f2()
               else:
                    return ['<h1>404</h1>'.encode('utf8')]
View Code

咱們也能夠傳入environ參數給f1()和f2(),這樣這兩個函數就能夠利用environ裏面的包裝的信息了。

因爲子路徑有多種,用if else效率並不高,所以咱們能夠用循環遍從來優化

代碼以下:

def routers():

            urlpatterns = (
                ('/book',f1),
                ('/web',f2),
            )
            return urlpatterns


        def application(environ, start_response):

            print(environ['PATH_INFO'])
            path=environ['PATH_INFO']
            start_response('200 OK', [('Content-Type', 'text/html')])


            urlpatterns = routers()
            func = None
            for item in urlpatterns:
                if item[0] == path:
                    func = item[1]
                    break
            if func:
                return func(environ)
            else:
                return ["<h1>404</h1>".encode("utf8")]
View Code

過程:將子路徑和所對應的函數都給封裝到一個元祖裏面,而後將這些元祖封裝到另外一個元祖裏面
   給urlpaytterns。將這些信息整合在routers函數裏面,在application函數裏面用for循環遍歷
      routers函數返回的信息,當item[0]跟客戶端(瀏覽器)輸入的一致時,就能夠調用item[1]傳遞
   給fun,而後break跳出循環接着執行下面的代碼,不然繼續循環遍歷。

優勢:1.添加新的子路徑時不用繼續死套if else語句,起了簡化做用。
      2.返回數據變活了

優化完源碼

from wsgiref.simple_server import make_server


def f1(environ):
    return [b'Hello book']
def f2(environ):
    return [b'Hello web']

def routers():
    urlpatterns = (
        ('/book', f1),
        ('/web', f2),
    )
    return urlpatterns


def application(environ, start_response):
    # 經過environ封裝成一個全部請求信息的對象
    # start_response能夠很方便的設置響應頭
    print(environ['PATH_INFO'])
    path = environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])

    urlpatterns = routers()
    func = None
    for item in urlpatterns:
        if item[0] == path:
            func = item[1]
            break
    if func:
        return func(environ)
    else:
        return ["<h1>404</h1>".encode("utf8")]

#封裝socket對象以及準備過程(socket,bind,listen)
httpd = make_server('', 8000, application)

print('Serving HTTP on port 8000...')
# 開始監聽HTTP請求:
httpd.serve_forever()
View Code

如今,咱們完成一個在瀏覽器頁面顯示時間的小做業,需求:當咱們在瀏覽器端輸入127.0.0.1:xxxx/

current_time時,在瀏覽器頁面打印出當前時間。

  • xxxx表示當前運行的端口號

 


 

做業答案區:

先創建一個HTML文件,內容以下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>current_time:  !cur_time!</h1>

</body>
</html>
View Code
接着在後端接受前端文件,對其進行修改返回給瀏覽器便可。代碼以下:

from wsgiref.simple_server import make_server
import time

def routers():

    urlpatterns = (
        ('/current_time',current_time),
    )
    return urlpatterns

def current_time(request):


    cur_time = time.ctime(time.time())  # ctime裏面傳一個時間戳 而time.time()就算時間戳
    f = open('current_time.html','rb')
    data = f.read()

    data = str(data,'utf8').replace('!cur_time!',str(cur_time))

    return [data.encode('utf8')]


def application(environ, start_response):

    print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])


    urlpatterns = routers()
    func = None
    for item in urlpatterns:
        if item[0] == path:
            func = item[1]
            break
    if func:
        return func(environ)
    else:
        return ["<h1>404</h1>".encode("utf8")]

httpd = make_server('', 8084, application)

print('Serving HTTP on port 8084...')

# 開始監聽HTTP請求:

httpd.serve_forever()
View Code

 

這是第一次寫博客記錄學習~   多謝支持~~

相關文章
相關標籤/搜索