<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
接收web伺服器的動態資源請求,給web伺服器提供處理動態資源請求的服務。根據請求資源路徑的字尾名進行判斷:
如果請求資源路徑的字尾名是.html則是動態資源請求, 讓web框架程式進行處理。
否則是靜態資源請求,讓web伺服器程式進行處理。
1、接受使用者端HTTP請求(底層是TCP)
# -*- coding: utf-8 -*- # @File : My_Web_Server.py # @author: Flyme awei # @email : 1071505897@qq.com # @Time : 2022/7/24 21:28 from socket import * import threading # 開發自己的Web伺服器主類 class MyHttpWebServer(object): def __init__(self, port): # 建立 HTTP服務的 TCP通訊端 server_socket = socket(AF_INET, SOCK_STREAM) # 設定埠號互用,程式退出之後不需要等待,直接釋放埠 server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, True) # 繫結 ip和 port server_socket.bind(('', port)) # listen使通訊端變為了被動連線 server_socket.listen(128) self.server_socket = server_socket # 處理請求函數 @staticmethod # 靜態方法 def handle_browser_request(new_socket): # 接受使用者端發來的資料 recv_data = new_socket.recv(4096) # 如果沒有資料,那麼請求無效,關閉通訊端,直接退出 if len(recv_data) == 0: new_socket.close() return # 啟動伺服器,並接受使用者端請求 def start(self): # 迴圈並多執行緒來接收使用者端請求 while True: # accept等待使用者端連線 new_socket, ip_port = self.server_socket.accept() print("使用者端ip和埠", ip_port) # 一個使用者端的請求交給一個執行緒來處理 sub_thread = threading.Thread(target=MyHttpWebServer.handle_browser_request, args=(new_socket, )) # 設定當前執行緒為守護執行緒 sub_thread.setDaemon(True) sub_thread.start() # 啟動子執行緒 # Web 伺服器程式的入口 def main(): web_server = MyHttpWebServer(8080) web_server.start() if __name__ == '__main__': main()
2、判斷請求是否是靜態資源還是動態資源
# 對接收的位元組資料進行轉換為字元資料 request_data = recv_data.decode('utf-8') print("瀏覽器請求的資料:", request_data) request_array = request_data.split(' ', maxsplit=2) # 得到請求路徑 request_path = request_array[1] print("請求的路徑是:", request_path) if request_path == "/": # 如果請求路徑為根目錄,自動設定為:/index.html request_path = "/index.html" # 判斷是否為:.html 結尾 if request_path.endswith(".html"): "動態資源請求" pass else: "靜態資源請求" pass
3、如果靜態資源怎麼處理?
"靜態資源請求" # 根據請求路徑讀取/static 目錄中的檔案資料,相應給使用者端 response_body = None # 響應主體 response_header = None # 響應頭的第一行 response_first_line = None # 響應頭內容 response_type = 'test/html' # 預設響應型別 try: # 讀取 static目錄中相對應的檔案資料,rb模式是一種相容模式,可以開啟圖片,也可以開啟js with open('static'+request_path, 'rb') as f: response_body = f.read() if request_path.endswith('.jpg'): response_type = 'image/webp' response_first_line = 'HTTP/1.1 200 OK' response_header = 'Content-Length:' + str(len(response_body)) + 'rn' + 'Content-Type: ' + response_type + '; charset=utf-8rn' + 'Date:' + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + 'rn' + 'Server: Flyme awei Serverrn' # 瀏覽器讀取的檔案可能不存在 except Exception as e: with open('static/404.html', 'rb') as f: response_body = f.read() # 響應的主體頁面內容 # 響應頭 response_first_line = 'HTTP/1.1 404 Not Foundrn' response_header = 'Content-Length:'+str(len(response_body))+'rn' + 'Content-Type: text/html; charset=utf-8rn' + 'Date:' + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + 'rn' + 'Server: Flyme awei Serverrn' # 最後都會執行的程式碼 finally: # 組成響應資料傳送給(使用者端)瀏覽器 response = (response_first_line + response_header + 'rn').encode('utf-8') + response_body new_socket.send(response) # 關閉通訊端 new_socket.close()
靜態資源請求驗證:
4、如果動態資源又怎麼處理
if request_path.endswith(".html"): "動態資源請求" # 動態資源的處理交給Web框架來處理,需要把請求引數交給Web框架,可能會有多個引數,採用字典結構 params = { 'request_path': request_path } # Web框架處理動態資源請求後,返回一個響應 response = MyFramework.handle_request(params) new_socket.send(response) new_socket.close()
5、關閉Web伺服器
new_socket.close()
Web伺服器主體框架總程式碼展示:
# -*- coding: utf-8 -*- # @File : My_Web_Server.py # @author: Flyme awei # @email : 1071505897@qq.com # @Time : 2022/7/24 21:28 import sys import time from socket import * import threading import MyFramework # 開發自己的Web伺服器主類 class MyHttpWebServer(object): def __init__(self, port): # 建立 HTTP服務的 TCP通訊端 server_socket = socket(AF_INET, SOCK_STREAM) # 設定埠號互用,程式退出之後不需要等待,直接釋放埠 server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, True) # 繫結 ip和 port server_socket.bind(('', port)) # listen使通訊端變為了被動連線 server_socket.listen(128) self.server_socket = server_socket # 處理請求函數 @staticmethod # 靜態方法 def handle_browser_request(new_socket): # 接受使用者端發來的資料 recv_data = new_socket.recv(4096) # 如果沒有資料,那麼請求無效,關閉通訊端,直接退出 if len(recv_data) == 0: new_socket.close() return # 對接收的位元組資料進行轉換為字元資料 request_data = recv_data.decode('utf-8') print("瀏覽器請求的資料:", request_data) request_array = request_data.split(' ', maxsplit=2) # 得到請求路徑 request_path = request_array[1] print("請求的路徑是:", request_path) if request_path == "/": # 如果請求路徑為根目錄,自動設定為:/index.html request_path = "/index.html" # 判斷是否為:.html 結尾 if request_path.endswith(".html"): "動態資源請求" # 動態資源的處理交給Web框架來處理,需要把請求引數交給Web框架,可能會有多個引數,採用字典結構 params = { 'request_path': request_path } # Web框架處理動態資源請求後,返回一個響應 response = MyFramework.handle_request(params) new_socket.send(response) new_socket.close() else: "靜態資源請求" # 根據請求路徑讀取/static 目錄中的檔案資料,相應給使用者端 response_body = None # 響應主體 response_header = None # 響應頭的第一行 response_first_line = None # 響應頭內容 response_type = 'test/html' # 預設響應型別 try: # 讀取 static目錄中相對應的檔案資料,rb模式是一種相容模式,可以開啟圖片,也可以開啟js with open('static'+request_path, 'rb') as f: response_body = f.read() if request_path.endswith('.jpg'): response_type = 'image/webp' response_first_line = 'HTTP/1.1 200 OK' response_header = 'Content-Length:' + str(len(response_body)) + 'rn' + 'Content-Type: ' + response_type + '; charset=utf-8rn' + 'Date:' + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + 'rn' + 'Server: Flyme awei Serverrn' # 瀏覽器讀取的檔案可能不存在 except Exception as e: with open('static/404.html', 'rb') as f: response_body = f.read() # 響應的主體頁面內容 # 響應頭 response_first_line = 'HTTP/1.1 404 Not Foundrn' response_header = 'Content-Length:'+str(len(response_body))+'rn' + 'Content-Type: text/html; charset=utf-8rn' + 'Date:' + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + 'rn' + 'Server: Flyme awei Serverrn' # 最後都會執行的程式碼 finally: # 組成響應資料傳送給(使用者端)瀏覽器 response = (response_first_line + response_header + 'rn').encode('utf-8') + response_body new_socket.send(response) # 關閉通訊端 new_socket.close() # 啟動伺服器,並接受使用者端請求 def start(self): # 迴圈並多執行緒來接收使用者端請求 while True: # accept等待使用者端連線 new_socket, ip_port = self.server_socket.accept() print("使用者端ip和埠", ip_port) # 一個使用者端的請求交給一個執行緒來處理 sub_thread = threading.Thread(target=MyHttpWebServer.handle_browser_request, args=(new_socket, )) # 設定當前執行緒為守護執行緒 sub_thread.setDaemon(True) sub_thread.start() # 啟動子執行緒 # Web 伺服器程式的入口 def main(): web_server = MyHttpWebServer(8080) web_server.start() if __name__ == '__main__': main()
1、根據請求路徑,動態的響應對應的資料
# -*- coding: utf-8 -*- # @File : MyFramework.py # @author: Flyme awei # @email : 1071505897@qq.com # @Time : 2022/7/25 14:05 import time # 自定義Web框架 # 處理動態資源請求的函數 def handle_request(parm): request_path = parm['request_path'] if request_path == '/index.html': # 當前請求路徑有與之對應的動態響應,當前框架只開發了 index.html的功能 response = index() return response else: # 沒有動態資源的資料,返回404頁面 return page_not_found() # 當前 index函數,專門處理index.html的請求 def index(): # 需求,在頁面中動態顯示當前系統時間 data = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) response_body = data response_first_line = 'HTTP/1.1 200 OKrn' response_header = 'Content-Length:' + str(len(response_body)) + 'rn' + 'Content-Type: text/html; charset=utf-8rn' + 'Date:' + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + 'rn' + 'Server: Flyme awei Serverrn' response = (response_first_line + response_header + 'rn' + response_body).encode('utf-8') return response def page_not_found(): with open('static/404.html', 'rb') as f: response_body = f.read() # 響應的主體頁面內容 # 響應頭 response_first_line = 'HTTP/1.1 404 Not Foundrn' response_header = 'Content-Length:' + str(len(response_body)) + 'rn' + 'Content-Type: text/html; charset=utf-8rn' + 'Date:' + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + 'rn' + 'Server: Flyme awei Serverrn' response = (response_first_line + response_header + 'rn').encode('utf-8') + response_body return response
2、如果請求路徑,沒有對應的響應資料也需要返回404頁面
1、自己設計一個模板 index.html ,中有一些地方採用動態的資料來替代
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>首頁 - 電影列表</title> <link href="/css/bootstrap.min.css" rel="stylesheet"> <script src="/js/jquery-1.12.4.min.js"></script> <script src="/js/bootstrap.min.js"></script> </head> <body> <div class="navbar navbar-inverse navbar-static-top "> <div class="container"> <div class="navbar-header"> <button class="navbar-toggle" data-toggle="collapse" data-target="#mymenu"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a href="#" class="navbar-brand">電影列表</a> </div> <div class="collapse navbar-collapse" id="mymenu"> <ul class="nav navbar-nav"> <li class="active"><a href="">電影資訊</a></li> <li><a href="">個人中心</a></li> </ul> </div> </div> </div> <div class="container"> <div class="container-fluid"> <table class="table table-hover"> <tr> <th>序號</th> <th>名稱</th> <th>導演</th> <th>上映時間</th> <th>票房</th> <th>電影時長</th> <th>型別</th> <th>備註</th> <th>刪除電影</th> </tr> {%datas%} </table> </div> </div> </body> </html>
2、怎麼替代,替代什麼資料
response_body = response_body.replace('{%datas%}', data)
1、以後開發新的動作資源的功能,只需要:
a、增加一個條件判斷分支
b、增加一個專門處理的函數
2、路由: 就是請求的URL路徑和處理常式直接的對映。
3、路由表
請求路徑 | 處理常式 |
---|---|
/index.html | index函數 |
/user_info.html | user_info函數 |
# 定義路由表 route_list = { ('/index.html', index), ('/user_info.html', user_info) } for path, func in route_list: if request_path == path: return func() else: # 沒有動態資源的資料,返回404頁面 return page_not_found()
注意:使用者的動態資源請求,通過遍歷路由表找到對應的處理常式來完成的。
1、採用帶引數的裝飾器
# -*- coding: utf-8 -*- # @File : My_Web_Server.py # @author: Flyme awei # @email : 1071505897@qq.com # @Time : 2022/7/24 21:28 # 定義路由表 route_list = [] # route_list = { # ('/index.html', index), # ('/user_info.html', user_info) # } # 定義一個帶引數的裝飾器 def route(request_path): # 引數就是URL請求 def add_route(func): # 新增路由表 route_list.append((request_path, func)) @wraps(func) def invoke(*args, **kwargs): # 呼叫指定的處理常式,並返回結果 return func() return invoke return add_route # 處理動態資源請求的函數 def handle_request(parm): request_path = parm['request_path'] # if request_path == '/index.html': # 當前請求路徑有與之對應的動態響應,當前框架只開發了 index.html的功能 # response = index() # return response # elif request_path == '/user_info.html': # 個人中心的功能 # return user_info() # else: # # 沒有動態資源的資料,返回404頁面 # return page_not_found() for path, func in route_list: if request_path == path: return func() else: # 沒有動態資源的資料,返回404頁面 return page_not_found()
2、在任何一個處理常式的基礎上增加一個新增路由的功能
@route('/user_info.html')
小結:使用帶引數的裝飾器,可以把我們的路由自動的,新增到路由表中。
1、查詢資料
my_web.py
# -*- coding: utf-8 -*- # @File : My_Web_Server.py # @author: Flyme awei # @email : 1071505897@qq.com # @Time : 2022/7/24 21:28 import socket import sys import threading import time import MyFramework # 開發自己的Web伺服器主類 class MyHttpWebServer(object): def __init__(self, port): # 建立HTTP伺服器的通訊端 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 設定埠號複用,程式退出之後不需要等待幾分鐘,直接釋放埠 server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) server_socket.bind(('', port)) server_socket.listen(128) self.server_socket = server_socket # 處理瀏覽器請求的函數 @staticmethod def handle_browser_request(new_socket): # 接受使用者端傳送過來的資料 recv_data = new_socket.recv(4096) # 如果沒有收到資料,那麼請求無效,關閉通訊端,直接退出 if len(recv_data) == 0: new_socket.close() return # 對接受的位元組資料,轉換成字元 request_data = recv_data.decode('utf-8') print("瀏覽器請求的資料:", request_data) request_array = request_data.split(' ', maxsplit=2) # 得到請求路徑 request_path = request_array[1] print('請求路徑是:', request_path) if request_path == '/': # 如果請求路徑為跟目錄,自動設定為/index.html request_path = '/index.html' # 根據請求路徑來判斷是否是動態資源還是靜態資源 if request_path.endswith('.html'): '''動態資源的請求''' # 動態資源的處理交給Web框架來處理,需要把請求引數傳給Web框架,可能會有多個引數,所有采用字典機構 params = { 'request_path': request_path, } # Web框架處理動態資源請求之後,返回一個響應 response = MyFramework.handle_request(params) new_socket.send(response) new_socket.close() else: '''靜態資源的請求''' response_body = None # 響應主體 response_header = None # 響應頭 response_first_line = None # 響應頭的第一行 # 其實就是:根據請求路徑讀取/static目錄中靜態的檔案資料,響應給使用者端 try: # 讀取static目錄中對應的檔案資料,rb模式:是一種相容模式,可以開啟圖片,也可以開啟js with open('static' + request_path, 'rb') as f: response_body = f.read() if request_path.endswith('.jpg'): response_type = 'image/webp' response_first_line = 'HTTP/1.1 200 OK' response_header = 'Server: Laoxiao_Serverrn' except Exception as e: # 瀏覽器想讀取的檔案可能不存在 with open('static/404.html', 'rb') as f: response_body = f.read() # 響應的主體頁面內容(位元組) # 響應頭 (字元資料) response_first_line = 'HTTP/1.1 404 Not Foundrn' response_header = 'Server: Laoxiao_Serverrn' finally: # 組成響應資料,傳送給使用者端(瀏覽器) response = (response_first_line + response_header + 'rn').encode('utf-8') + response_body new_socket.send(response) new_socket.close() # 關閉通訊端 # 啟動伺服器,並且接受使用者端的請求 def start(self): # 迴圈並且多執行緒來接受使用者端的請求 while True: new_socket, ip_port = self.server_socket.accept() print("使用者端的ip和埠", ip_port) # 一個使用者端請求交給一個執行緒來處理 sub_thread = threading.Thread(target=MyHttpWebServer.handle_browser_request, args=(new_socket,)) sub_thread.setDaemon(True) # 設定當前執行緒為守護執行緒 sub_thread.start() # 子執行緒要啟動 # web伺服器程式的入口 def main(): web_server = MyHttpWebServer(8080) web_server.start() if __name__ == '__main__': main()
MyFramework.py
# -*- coding: utf-8 -*- # @File : My_Web_Server.py # @author: Flyme awei # @email : 1071505897@qq.com # @Time : 2022/7/24 21:28 import time from functools import wraps import pymysql # 定義路由表 route_list = [] # route_list = { # # ('/index.html',index), # # ('/userinfo.html',user_info) # } # 定義一個帶引數裝飾器 def route(request_path): # 引數就是URL請求 def add_route(func): # 新增路由到路由表 route_list.append((request_path, func)) @wraps(func) def invoke(*arg, **kwargs): # 呼叫我們指定的處理常式,並且返回結果 return func() return invoke return add_route # 處理動態資源請求的函數 def handle_request(params): request_path = params['request_path'] for path, func in route_list: if request_path == path: return func() else: # 沒有動態資源的資料,返回404頁面 return page_not_found() # if request_path =='/index.html': # 當前的請求路徑有與之對應的動態響應,當前框架,我只開發了index.html的功能 # response = index() # return response # # elif request_path =='/userinfo.html': # 個人中心的功能,user_info.html # return user_info() # else: # # 沒有動態資源的資料,返回404頁面 # return page_not_found() # 當前user_info函數,專門處理userinfo.html的動態請求 @route('/userinfo.html') def user_info(): # 需求:在頁面中動態顯示當前系統時間 date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) # response_body =data with open('template/user_info.html', 'r', encoding='utf-8') as f: response_body = f.read() response_body = response_body.replace('{%datas%}', date) response_first_line = 'HTTP/1.1 200 OKrn' response_header = 'Server: Laoxiao_Serverrn' response = (response_first_line + response_header + 'rn' + response_body).encode('utf-8') return response # 當前index函數,專門處理index.html的請求 @route('/index.html') def index(): # 需求:從資料庫中取得所有的電影資料,並且動態展示 # date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) # response_body =data # 1、從MySQL中查詢資料 conn = pymysql.connect(host='localhost', port=3306, user='root', password='******', database='test', charset='utf8') cursor = conn.cursor() cursor.execute('select * from t_movies') result = cursor.fetchall() # print(result) datas = "" for row in result: datas += '''<tr> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s 億人民幣</td> <td>%s</td> <td>%s</td> <td>%s</td> <td> <input type='button' value='刪除'/> </td> </tr> ''' % row print(datas) # 把查詢的資料,轉換成動態內容 with open('template/index.html', 'r', encoding='utf-8') as f: response_body = f.read() response_body = response_body.replace('{%datas%}', datas) response_first_line = 'HTTP/1.1 200 OKrn' response_header = 'Server: Laoxiao_Serverrn' response = (response_first_line + response_header + 'rn' + response_body).encode('utf-8') return response # 處理沒有找到對應的動態資源 def page_not_found(): with open('static/404.html', 'rb') as f: response_body = f.read() # 響應的主體頁面內容(位元組) # 響應頭 (字元資料) response_first_line = 'HTTP/1.1 404 Not Foundrn' response_header = 'Server: Laoxiao_Serverrn' response = (response_first_line + response_header + 'rn').encode('utf-8') + response_body return response
2、根據查詢的資料得到動態的內容
到此這篇關於Python開發自定義Web框架的範例詳解的文章就介紹到這了,更多相關Python Web框架內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45