1.WSGI協議概述(Python Web Server Gateway Interface)
1.WSGI允許開發者將選擇web框架和web服務器分開,可以混合匹配web服務器和web框架,選擇一個適合的配對
2.WSGI協議在不修改服務器和架構代碼情況下確保了可以在多個架構下運行web服務器
3.Web服務器必須具備WSGI介面,所有的現代Python Web框架都已具備WSGI介面
4.WSGI介面讓開發者不對代碼作修改就能使服務器和特點的Web框架協同作業
5.瀏覽器請求WSGI_Server回應流程圖: https://www.processon.com/view/link/5efcac3507912929cb6b33df
2.定義WSGI介面
def application(environ, start_response): """遵循WSGI標準的HTTP處理函式 :param environ: 一個包含所有HTTP請求資訊的dict物件 :param start_response: 一個發送HTTP回應的函式 :return: 回傳body資訊 """ start_response('200 OK', [('Content-Type', 'text/html')]) return 'Hello World!'
3.Web服務器-WSGI協議-web框架傳遞的字典
{ 'HTTP_ACCEPT_LANGUAGE': 'zh-cn', 'wsgi.file_wrapper': <built-infunctionuwsgi_sendfile>, 'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 'uwsgi.version': b'2.0.15', 'REMOTE_ADDR': '172.16.7.1', 'wsgi.errors': <_io.TextIOWrappername=2mode='w'encoding='UTF-8'>, 'wsgi.version': (1,0), 'REMOTE_PORT': '40432', 'REQUEST_URI': '/', 'SERVER_PORT': '8000', 'wsgi.multithread': False, 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'HTTP_HOST': '172.16.7.152: 8000', 'wsgi.run_once': False, 'wsgi.input': <uwsgi._Inputobjectat0x7f7faecdc9c0>, 'SERVER_PROTOCOL': 'HTTP/1.1', 'REQUEST_METHOD': 'GET', 'HTTP_ACCEPT_ENCODING': 'gzip,deflate', 'HTTP_CONNECTION': 'keep-alive', 'uwsgi.node': b'ubuntu', 'HTTP_DNT': '1', 'UWSGI_ROUTER': 'http', 'SCRIPT_NAME': '', 'wsgi.multiprocess': False, 'QUERY_STRING': '', 'PATH_INFO': '/index.html', 'wsgi.url_scheme': 'http', 'HTTP_USER_AGENT': 'Mozilla/5.0(Macintosh;IntelMacOSX10_12_5)AppleWebKit/603.2.4(KHTML,likeGecko)Version/10.1.1Safari/603.2.4', 'SERVER_NAME': 'ubuntu' }
4.Web動態服務器-多行程
# html檔案夾網盤鏈接: https://pan.baidu.com/s/1wbZ92KLstff3GurLV_C0lg 密碼: hp9o # 下載完命令列解壓后放到程式的同級路徑下,解壓命令: tar -zxvf 06_html.tar.gz -C ./
1.專案目錄結構:
~/Desktop/Python/06_Web動態服務器 $ tree . ├── html │ ├── index.html │ ├── ... ├── web │ ├── __pycache__ │ │ └── mini_frame.cpython-37.pyc │ └── mini_frame.py └── web_server.py
2.web_server.py檔案代碼
import time import socket import sys import re import multiprocessing class WSGIServer(object): """定義一個WSGI服務器的類""" def __init__(self, port, documents_root): # 1. 創建套接字 self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2.設定當服務器先close 即服務器端4次揮手之后資源能夠立即釋放,保證下次運行程式時可以立即系結7890埠 self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 3.系結服務器地址 self.server_socket.bind(("", port)) # 4.變為監聽套接字 self.server_socket.listen(128) # 設定資源檔案的路徑 self.documents_root = documents_root def set_app(self, app): """設定web框架可以呼叫的函式(物件)""" self.app = app def run_forever(self): """回圈運行服務器,等待客戶端鏈接并為客戶端服務""" # 等待對方鏈接 while True: # 5.等待客戶端鏈接 new_socket, new_addr = self.server_socket.accept() # 6.創建一個新的行程來完成這個客戶端的請求任務 new_socket.settimeout(3) # 設定套接字的超時檢測3s new_process = multiprocessing.Process(target=self.deal_with_request, args=(new_socket,)) new_process.start() # 因為子行程已經復制了父行程的套接字等資源,所以父行程呼叫close不會將他們對應的這個鏈接關閉的 new_socket.close() def deal_with_request(self, client_socket): """用一個新的行程以長鏈接的方式,為這個瀏覽器服務""" while True: try: # 1.接收瀏覽器發送過來的HTTP請求 request = client_socket.recv(1024).decode("utf-8") except Exception as ret: print("========>", ret) client_socket.close() return # 判斷瀏覽器是否關閉 if not request: client_socket.close() return request_lines = request.splitlines() for i, line in enumerate(request_lines): print(i, line) # 提取請求的檔案(index.html) # GET /a/b/c/d/e/index.html HTTP/1.1 ret = re.match(r"([^/]*)([^ ]+)", request_lines[0]) # 如果沒有指定訪問哪個頁面,則默認訪問index.html # GET / HTTP/1.1 if ret: print("正則提取資料:", ret.group(1)) print("正則提取資料:", ret.group(2)) file_name = ret.group(2) if file_name == "/": file_name = "/index.html" # 2.回傳HTTP格式的資料給瀏覽器 # 2.1如果請求的資源不是以.py結尾,那么就是請求靜態資源 if not file_name.endswith(".py"): # 讀取檔案資料 try: f = open(self.documents_root + file_name, "rb") except: response_body = "file not found, Please enter the correct URL." response_header = "HTTP/1.1 404 not found\r\n" response_header += "Content-Type: text/html; charset=utf-8\r\n" response_header += "Content-Length: %d\r\n" % (len(response_body)) response_header += "\r\n" response = response_header + response_body # 沒有對應的回應,回傳404表示沒有這個頁面 client_socket.send(response.encode('utf-8')) else: content = f.read() f.close() response_body = content response_header = "HTTP/1.1 200 OK\r\n" response_header += "Content-Length: %d\r\n" % (len(response_body)) response_header += "\r\n" # 將header回傳給瀏覽器 client_socket.send(response_header.encode('utf-8') + response_body) # 2.2如果請求的資源是以.py結尾,那么就是請求動態資源 else: # 準備一個字典,里面存放需要傳遞給web框架的資料 env = {} # 存web回傳的資料 response_body = self.app(env, self.set_response_headers) # 合并header和body response_header = "HTTP/1.1 {status}\r\n".format(status=self.headers[0]) response_header += "Content-Type: text/html; charset=utf-8\r\n" response_header += "Content-Length: %d\r\n" % len(response_body) for temp_head in self.headers[1]: response_header += "{0}:{1}\r\n".format(*temp_head) response = response_header + "\r\n" response += response_body client_socket.send(response.encode('utf-8')) def set_response_headers(self, status, headers): """此方法會在web框架中被默認呼叫""" # 添加服務器的一些資訊 response_header_default = [ ("Data", time.ctime()), ("Server", "ItCast-python mini web server") ] # 將web框架中傳遞回的狀態碼/回應頭資訊存盤起來 # [字串, [xxxxx, xxx2]] self.headers = [status, response_header_default + headers] # 設定靜態資源訪問的路徑 g_static_document_root = "./html" # 設定動態資源訪問的路徑 g_dynamic_document_root = "./web" def main(): """控制web服務器整體""" # python3 web_server.py 7890 mini_frame:application if len(sys.argv) == 3: try: # 獲取web服務器的port port = sys.argv[1] if port.isdigit(): port = int(port) # 獲取web服務器需要動態資源時,訪問的web框架名字 web_frame_module_app_name = sys.argv[2] except Exception as ret: print("埠輸入錯誤...") return else: print("運行方式如: python3 web_server.py 7890 mini_frame:application") return print("http服務器使用的port:%s" % port) # 將動態路徑即存放py檔案的路徑,添加到path中,python解釋器才可以找到路徑 sys.path.append(g_dynamic_document_root) ret = re.match(r"([^:]*):(.*)", web_frame_module_app_name) if ret: # 獲取模塊名 web_frame_module_name = ret.group(1) # 獲取可以呼叫web框架的應用名稱 app_name = ret.group(2) # 匯入web框架的主模塊,回傳值標記這個匯入的模塊 web_frame_module = __import__(web_frame_module_name) # 獲取那個可以直接呼叫的函式(物件) app = getattr(web_frame_module, app_name) # print(app) # for test # 啟動http服務器 http_server = WSGIServer(port, g_static_document_root) # 將方法封裝成類的屬性 http_server.set_app(app) # 運行http服務器 http_server.run_forever() if __name__ == "__main__": main()
3.mini_frame.py檔案代碼
import time def application(environ, start_response): """遵循WSGI標準的HTTP處理函式 :param environ: 一個包含所有HTTP請求資訊的dict物件 :param start_response: 一個發送HTTP回應的函式 :return: 回傳body資訊 """ status = "200 OK" response_headers = [("Content-Type", "text/html")] start_response(status, response_headers) return str(environ) + "==Hello world from a simple WSGI application!--->%s\n" % time.ctime()
4.完整專案網盤鏈接: https://pan.baidu.com/s/1CpO1502f59gEgwCsXaYXlA 密碼: flnq
5.mini-web框架
1.專案目錄結構:
~/Desktop/python3/07_mini-web框架 $ tree -L 2 . ├── __init__.py ├── dynamic # 存放py模塊 │ ├── __init__.py │ ├── __pycache__ │ └── mini_frame.py # mini框架 ├── log.txt # 日志 ├── readme.txt # 說明檔案 ├── run.sh # shell運行腳本 ├── static │ ├── css │ └── js ├── stock_db.sql # 資料庫資料準備生成腳本 ├── templates # 存放模板檔案 │ ├── center.html # 個人資訊界面 │ ├── index.html # 股票資訊界面 │ └── update.html # 修改備注頁面 ├── web_server.conf # mini web服務器組態檔 └── web_server.py # mini web服務器
2.資料庫準備
-- 創建資料庫 create database stock_db charset=utf8; -- 選中資料庫 use stock_db; -- 匯入資料,sql檔案在完整專案網盤鏈接解壓檔案中 source stock_db.sql
3.web_server.py檔案代碼
import time import socket import sys import re import multiprocessing class WSGIServer(object): """定義一個WSGI服務器的類""" def __init__(self, port, documents_root): # 1. 創建套接字 self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2.設定當服務器先close 即服務器端4次揮手之后資源能夠立即釋放,保證下次運行程式時可以立即系結7890埠 self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 3.系結服務器地址 self.server_socket.bind(("", port)) # 4.變為監聽套接字 self.server_socket.listen(128) # 設定資源檔案的路徑 self.documents_root = documents_root def set_app(self, app): """設定web框架可以呼叫的函式(物件)""" self.app = app def run_forever(self): """回圈運行服務器,等待客戶端鏈接并為客戶端服務""" # 等待對方鏈接 while True: # 5.等待客戶端鏈接 new_socket, new_addr = self.server_socket.accept() # 6.創建一個新的行程來完成這個客戶端的請求任務 new_socket.settimeout(3) # 設定套接字的超時監測3s new_process = multiprocessing.Process(target=self.deal_with_request, args=(new_socket,)) new_process.start() # 因為子行程已經復制了父行程的套接字等資源,所以父行程呼叫close不會將他們對應的這個鏈接關閉的 new_socket.close() def deal_with_request(self, client_socket): """用一個新的行程以長鏈接的方式,為這個瀏覽器服務""" while True: try: # 1.接收瀏覽器發送過來的HTTP請求 request = client_socket.recv(1024).decode("utf-8") except Exception as ret: print("========>", ret) client_socket.close() return # 判斷瀏覽器是否關閉 if not request: client_socket.close() return request_lines = request.splitlines() for i, line in enumerate(request_lines): print(i, line) # 提取請求的檔案(index.html) # GET /a/b/c/d/e/index.html HTTP/1.1 ret = re.match(r"([^/]*)([^ ]+)", request_lines[0]) # 如果沒有指定訪問哪個頁面,則默認訪問index.html # GET / HTTP/1.1 if ret: print("正則提取資料:", ret.group(1)) print("正則提取資料:", ret.group(2)) file_name = ret.group(2) if file_name == "/": file_name = "/index.html" # 2.回傳HTTP格式的資料給瀏覽器 # 2.1如果請求的資源不是以.html結尾,那么就是請求靜態資源 if not file_name.endswith(".html"): # 讀取檔案資料 try: print(self.documents_root + file_name) f = open(self.documents_root + file_name, "rb") except: response_body = "file not found, 請輸入正確的URL..." response_header = "HTTP/1.1 404 not found\r\n" response_header += "Content-Type: text/html; charset=utf-8\r\n" response_header += "Content-Length: %d\r\n" % (len(response_body.encode("utf-8"))) response_header += "\r\n" response = response_header + response_body # 沒有對應的回應,回傳404表示沒有這個頁面 client_socket.send(response.encode("utf-8")) else: content = f.read() f.close() response_body = content response_header = "HTTP/1.1 200 OK\r\n" response_header += "Content-Length: %d\r\n" % (len(response_body)) response_header += "\r\n" # 將靜態請求回傳給瀏覽器 client_socket.send(response_header.encode('utf-8') + response_body) # 2.2如果請求的資源是以.html結尾,那么就是請求動態資源 else: # 準備一個字典,里面存放需要傳遞給web框架的資料 env = dict() env["PATH_INFO"] = file_name # 例如 index.py # 存web回傳的資料 response_body = self.app(env, self.set_response_headers) # 合并header和body response_header = "HTTP/1.1 {status}\r\n".format(status=self.headers[0]) response_header += "Content-Type: text/html; charset=utf-8\r\n" response_header += "Content-Length: %d\r\n" % len(response_body.encode("utf-8")) for temp_head in self.headers[1]: response_header += "{0}:{1}\r\n".format(*temp_head) response = response_header + "\r\n" response += response_body client_socket.send(response.encode('utf-8')) def set_response_headers(self, status, headers): """此方法會在web框架中被默認呼叫""" # 添加服務器的一些資訊 response_header_default = [ ("Data", time.ctime()), ("Server", "ItCast-python mini web server") ] # 將web框架中傳遞回的狀態碼/回應頭資訊存盤起來 # [字串, [xxxxx, xxx2]] self.headers = [status, response_header_default + headers] # 設定靜態資源訪問的路徑 # g_static_document_root = "./html" # # 設定動態資源訪問的路徑 # g_dynamic_document_root = "./web" def main(): """控制web服務器整體""" # python3 web_server.py 7890 mini_frame:application if len(sys.argv) == 3: try: # 獲取web服務器的port port = sys.argv[1] if port.isdigit(): port = int(port) # 獲取web服務器需要動態資源時,訪問的web框架名字 web_frame_module_app_name = sys.argv[2] except Exception as ret: print("埠輸入錯誤...") return else: print("運行方式如: python3 web_server.py 7890 mini_frame:application") return # 讀取組態檔資訊 with open("./web_server.conf") as f: conf_info = eval(f.read()) # conf_info字典里的資料為 # { # "static_path": "./static", # "dynamic_path": "./dynamic" # } print("http服務器使用的port:%s" % port) # 將動態路徑即存放py檔案的路徑,添加到path中,python解釋器才可以找到路徑 sys.path.append(conf_info["dynamic_path"]) ret = re.match(r"([^:]*):(.*)", web_frame_module_app_name) if ret: # 獲取模塊名 web_frame_module_name = ret.group(1) # 獲取可以呼叫web框架的應用名稱 app_name = ret.group(2) # 匯入web框架的主模塊,回傳值標記這個匯入的模塊 web_frame_module = __import__(web_frame_module_name) # 獲取那個可以直接呼叫的函式(物件) app = getattr(web_frame_module, app_name) # print(app) # for test # 啟動http服務器 http_server = WSGIServer(port, conf_info["static_path"]) # 將方法封裝成類的屬性 http_server.set_app(app) # 運行http服務器 http_server.run_forever() if __name__ == "__main__": main()
4.mini_frame.py檔案代碼
# import time # import os import re from urllib.parse import unquote import logging import pymysql template_root = "./templates" # 用來存放url路由映射 # url_route = { # "/index.html": index_func, # "/center.html": center_func # } g_url_route = dict() def route(url): def set_func(func): # 添加鍵值對,key是需要訪問的url,value是當這個url需要訪問的時候,需要呼叫的函式參考 g_url_route[url] = func def call_func(*args, **kwargs): return func(*args, **kwargs) return call_func return set_func @route(r"/index.html") def index(ret): """回傳index.py需要的頁面內容""" # return "hahha" + os.getcwd() # for test 路徑問題 try: f = open(template_root + "/index.html") except Exception as ret: return "打開股票資訊頁面產生了例外: %s" % ret else: content = f.read() f.close() # --------通過資料庫更新股票資訊資料------- # 創建connection連接 db = pymysql.connect(host="localhost", port=3306, user="root", password="123456", database="stock_db", charset="utf8") # 獲取cursor物件 cursor = db.cursor() sql = """select * from info;""" cursor.execute(sql) data_from_mysql = cursor.fetchall() cursor.close() db.close() html_template = """ <tr> <td>%d</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="https://www.cnblogs.com/tangxuecheng/p/添加" id="toAdd" name="toAdd" systemidvaule="%s"> </td> </tr>""" html = "" for info in data_from_mysql: html += html_template % (info[0], info[1], info[2], info[3], info[4], info[5], info[6], info[7], info[1]) content = re.sub(r"\{%content%\}", html, content) return content @route(r"/center.html") def center(ret): """回傳center.html需要的頁面內容""" # return "hahha" + os.getcwd() # for test 路徑問題 try: f = open(template_root + "/center.html") except Exception as ret: return "打開個人中心頁面產生了例外: %s" % ret else: content = f.read() f.close() # --------通過資料庫更新個人中心資料------- # 創建connection連接 db = pymysql.connect(host="localhost", port=3306, user="root", password="123456", database="stock_db", charset="utf8") # 獲取cursor物件 cursor = db.cursor() sql = """select i.code,i.short,i.chg,i.turnover,i.price,i.highs,j.note_info from info as i inner join focus as j on i.id=j.info_id;""" cursor.execute(sql) data_from_mysql = cursor.fetchall() cursor.close() db.close() html_template = """ <tr> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td> <a type="button" href="https://www.cnblogs.com/update/%s.html"> <span aria-hidden="true"></span> 修改 </a> </td> <td> <input type="button" value="https://www.cnblogs.com/tangxuecheng/p/洗掉" id="toDel" name="toDel" systemidvaule="%s"> </td> </tr> """ html = "" for info in data_from_mysql: html += html_template % (info[0], info[1], info[2], info[3], info[4], info[5], info[6], info[0], info[0]) content = re.sub(r"\{%content%\}", html, content) return content # 給路由添加正則運算式的原因: 在實際開發時,url中往往會帶有很多引數,例如/add/000007.html中000007就是引數 # 如果沒有正則的話,那么就需要撰寫N次@route來進行添加url對應的函式到字典中,此時字典中的鍵值對有N個,浪費空間 # 而采用了正則的話,那么只要撰寫1次@route就可以完成多個url例如/add/00007.html /add/000036.html等對應同一個函式 @route(r"/add/(\d+)\.html") def add_focus(ret): """添加對應股票的關注""" # 1.獲取股票代碼 stock_code = ret.group(1) # 2.判斷試下是否有這個股票代碼 # 創建connection連接 db = pymysql.connect(host="localhost", port=3306, user="root", password="123456", database="stock_db", charset="utf8") cursor = db.cursor() sql = """select * from info where code=%s;""" cursor.execute(sql, (stock_code,)) # 如果要是沒有這個股票代碼,那么就認為是非法的請求 if not cursor.fetchone(): cursor.close() db.close() return "沒有這支股票,大哥,我們是創業公司,請手下留情..." # 3.判斷以下是否已經關注過 sql = """ select * from info as i inner join focus as f on i.id=f.info_id where i.code=%s;""" cursor.execute(sql, (stock_code,)) # 如果查出來了,那么表示已經關注過 if cursor.fetchone(): cursor.close() cursor.close() return "已經關注過了,請勿重復關注..." # 4.添加關注 sql = """insert into focus (info_id) select id from info where code=%s;""" cursor.execute(sql, (stock_code,)) db.commit() cursor.close() db.close() return "關注成功...." @route(r"/del/(\d+)\.html") def del_focus(ret): """取消對應股票的關注""" # 1.獲取股票代碼 stock_code = ret.group(1) # 2.判斷試下是否有這個股票代碼 db = pymysql.connect(host="localhost", port=3306, user="root", password="123456", database="stock_db", charset="utf8") cursor = db.cursor() sql = """select * from info where code=%s;""" cursor.execute(sql, (stock_code,)) # 如果要是沒有這個股票代碼,那么就認為是非法的請求 if not cursor.fetchone(): cursor.close() db.close() return "沒有這支股票,大哥,我們是創業公司,請手下留情..." # 3. 判斷以下是否已經關注過 sql = """ select * from info as i inner join focus as f on i.id=f.info_id where i.code=%s;""" cursor.execute(sql, (stock_code,)) # 如果沒有關注過,那么表示非法的請求 if not cursor.fetchone(): cursor.close() db.close() return "%s之前未關注,請勿取消關注..." % stock_code # 4.取消關注 # sql = """insert into focus (info_id) select id from info where code=%s;""" sql = """delete from focus where info_id = (select id from info where code=%s);""" cursor.execute(sql, (stock_code,)) db.commit() cursor.close() db.close() return "取消關注成功...." @route(r"/update/(\d*)\.html") def update(ret): """顯示更新頁面的內容""" # 1.獲取股票代碼 stock_code = ret.group(1) # 2.打開模版 try: template_file_name = template_root + "/update.html" f = open(template_file_name) except Exception as ret: return "%s...沒有找到%s" % (ret, template_file_name) else: content = f.read() f.close() # 3. 根據股票代碼查詢相關的備注資訊 db = pymysql.connect(host="localhost", port=3306, user="root", password="123456", database="stock_db", charset="utf8") cursor = db.cursor() sql = """select f.note_info from focus as f inner join info as i on i.id=f.info_id where i.code=%s;""" cursor.execute(sql, (stock_code,)) stock_note_info = cursor.fetchone() cursor.close() db.close() content = re.sub(r"\{%code%\}", stock_code, content) content = re.sub(r"\{%note_info%\}", str(stock_note_info[0]), content) return content @route(r"/update/(\d*)/(.*)\.html") def update_note_info(ret): """進行資料的真正更新""" stock_code = ret.group(1) stock_note_info = ret.group(2) stock_note_info = unquote(stock_note_info) # 在向資料庫存盤時進行url解碼 # 創建connection連接 db = pymysql.connect(host="localhost", port=3306, user="root", password="123456", database="stock_db", charset="utf8") # 獲取cursor物件 cursor = db.cursor() sql = """update focus set note_info=%s where info_id = (select id from info where code=%s);""" cursor.execute(sql, (stock_note_info, stock_code)) db.commit() cursor.close() db.close() return "修改成功" def application(environ, start_response): """遵循WSGI標準的HTTP處理函式 :param environ: 一個包含所有HTTP請求資訊的dict物件 :param start_response: 一個發送HTTP回應的函式 :return: 回傳body資訊 """ status = '200 OK' response_headers = [('Content-Type', 'text/html')] start_response(status, response_headers) file_name = environ['PATH_INFO'] # 添加log日志功能 logging.basicConfig(level=logging.INFO, filename='./log.txt', filemode='a', format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s') logging.info("訪問的是: %s" % file_name) try: # return g_url_route[file_name](file_name) # 路由功能 for url, call_func in g_url_route.items(): print(url) ret = re.match(url, file_name) if ret: return call_func(ret) else: logging.warning("沒有對應的函式....") return "請求的url(%s)沒有對應的函式...." % file_name except Exception as ret: return "mini_frame框架產生了例外: %s" % ret
5.完整專案網盤鏈接: https://pan.baidu.com/s/1i7qdYFl0N10_AUrjJPK3Ow 密碼: o1qc
6.未實作的功能
1.把操作資料庫的部分單獨封裝到一個函式中,使用時直接呼叫
2.配置MySQL主從服務器-從服務器查詢操作,主服務器增刪改操作
3.用元類實作ORM-即操作資料庫部分用元類實作
6.標準庫模塊實作Web動態服務器
try: # Python2中的匯入 from BaseHTTPServer import BaseHTTPRequestHandler from BaseHTTPServer import HTTPServer except ImportError: # Python3中的匯入 from http.server import BaseHTTPRequestHandler from http.server import HTTPServer class RequestHander(BaseHTTPRequestHandler): """請求處理類""" def do_GET(self): """固定的處理GET請求方法""" # 查看請求頭 print(self.headers) print("Do method get") # 組織回應行 self.send_response(200) # 組織回應頭 self.send_header("Content-Type", "text/html") self.send_header("charset", "utf-8") # 回應頭結束 self.end_headers() # 發送回應體 self.wfile.write(b"<h1>Hello World!</h1>") return def do_POST(self): """固定的處理POST請求方法""" pass def main(): # 指定地址 address = ("0.0.0.0", 7890) # 生成服務器物件 server = HTTPServer(address, RequestHander) # 運行 server.serve_forever() if __name__ == "__main__": main()
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/1951.html
標籤:Python
下一篇:Python基礎語法知識點匯集
