(更新時間)2021年3月28日 python基礎知識(搭建自己的框架)

      網友投稿 918 2022-05-29

      一:框架程序

      1. 框架職責介紹

      接收web服務器的動態資源請求,給web服務器提供處理動態資源請求的服務。

      2. 動態資源判斷

      根據請求資源路徑的后綴名進行判斷

      如果請求資源路徑的后綴名是.html則是動態資源請求, 讓web框架程序進行處理。

      否則是靜態資源請求,讓web服務器程序進行處理。

      web服務器程序(web.py)代碼:

      import socket import threading import sys import framework # 定義web服務器類 class HttpWebServer(object): def __init__(self, port): # 創建tcp服務端套接字 tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 設置端口號復用, 程序退出端口立即釋放 tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 綁定端口號 tcp_server_socket.bind(("", port)) # 設置監聽 tcp_server_socket.listen(128) self.tcp_server_socket = tcp_server_socket # 處理客戶的請求 @staticmethod def handle_client_quest(new_socket): # 代碼執行到此,說明連接建立成功 recv_client_data = new_socket.recv(4096) if len(recv_client_data) == 0: print("關閉瀏覽器了") # 關閉服務與客戶端的套接字 new_socket.close() return # 對二進制數據進行解碼 recv_client_content = recv_client_data.decode("utf-8") print(recv_client_content) # 根據指定字符串進行分割, 最大分割次數指定2 request_list = recv_client_content.split(" ", maxsplit=2) # 獲取請求資源路徑 request_path = request_list[1] print(request_path) # 判斷請求的是否是根目錄,如果條件成立,指定首頁數據返回 if request_path == "/": request_path = "/index.html" # 判斷是否是動態資源請求 if request_path.endswith(".html"): """這里是動態資源請求,把請求信息交給框架處理""" # 字典存儲用戶的請求信息 env = { "request_path": request_path } # 獲取處理結果 status, headers, response_body = framework.handle_request(env) # 使用框架處理的數據拼接響應報文 # 響應行 response_line = "HTTP/1.1 %s\r\n" % status # 響應頭 response_header = "" # 遍歷頭部信息 for header in headers: # 拼接多個響應頭 response_header += "%s: %s\r\n" % header response_data = (response_line + response_header + "\r\n" + response_body).encode("utf-8") # 發送數據 new_socket.send(response_data) # 關閉socket new_socket.close() else: """這里是靜態資源請求""" try: # 動態打開指定文件 with open("static" + request_path, "rb") as file: # 讀取文件數據 file_data = file.read() except Exception as e: # 請求資源不存在,返回404數據 # 響應行 response_line = "HTTP/1.1 404 Not Found\r\n" # 響應頭 response_header = "Server: PWS1.0\r\n" with open("static/error.html", "rb") as file: file_data = file.read() # 響應體 response_body = file_data # 拼接響應報文 response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body # 發送數據 new_socket.send(response_data) else: # 響應行 response_line = "HTTP/1.1 200 OK\r\n" # 響應頭 response_header = "Server: PWS1.0\r\n" # 響應體 response_body = file_data # 拼接響應報文 response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body # 發送數據 new_socket.send(response_data) finally: # 關閉服務與客戶端的套接字 new_socket.close() def start(self): while True: # 等待接受客戶端的連接請求 new_socket, ip_port = self.tcp_server_socket.accept() sub_thread = threading.Thread(target=self.handle_client_quest, args=(new_socket,)) # 設置守護線程 sub_thread.setDaemon(True) sub_thread.start() # 程序入口函數 def main(): # 獲取命令行參數判斷長度 if len(sys.argv) != 2: print("執行命令如下: python3 xxx.py 9000") return # 判斷端口號是否是數字 if not sys.argv[1].isdigit(): print("執行命令如下: python3 xxx.py 9000") return # 需要轉成int類型 port = int(sys.argv[1]) # 創建web服務器 web_server = HttpWebServer(port) # 啟動web服務器 web_server.start() if __name__ == '__main__': main()

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      (更新時間)2021年3月28日 python基礎知識(搭建自己的框架)

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      85

      86

      87

      88

      89

      90

      91

      92

      93

      94

      95

      96

      97

      98

      99

      100

      101

      102

      103

      104

      105

      106

      107

      108

      109

      110

      111

      112

      113

      114

      115

      116

      117

      118

      119

      120

      121

      122

      123

      124

      125

      126

      127

      128

      129

      130

      131

      132

      133

      134

      135

      136

      137

      138

      139

      140

      141

      142

      143

      144

      145

      146

      3. 處理客戶端的動態資源請求

      創建web框架程序

      接收web服務器的動態資源請求

      處理web服務器的動態資源請求并把處理結果返回給web服務器

      web服務器把處理結果組裝成響應報文發送給瀏覽器

      web框架程序(framework.py)代碼:

      """miniweb框架,負責處理動態資源請求""" import time # 獲取首頁數據 def index(): # 響應狀態 status = "200 OK"; # 響應頭 response_header = [("Server", "PWS2.0")] # 處理后的數據 data = time.ctime() return status, response_header, data # 沒有找到動態資源 def not_found(): # 響應狀態 status = "404 Not Found"; # 響應頭 response_header = [("Server", "PWS2.0")] # 處理后的數據 data = "not found" return status, response_header, data # 處理動態資源請求 def handle_request(env): # 獲取動態請求資源路徑 request_path = env["request_path"] print("接收到的動態資源請求:", request_path) if request_path == "/index.html": # 獲取首頁數據 result = index() return result else: # 沒有找到動態資源 result = not_found() return result

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      4. 小結

      動態資源的判斷通過請求資源路徑的后綴是.html來完成,否則是靜態資源

      處理客戶端的動態資源請求 接收web服務器的動態資源請求 處理動態資源請求并把處理結果返回給web服務器

      web服務器把處理結果組裝成響應報文發送給瀏覽器

      二:模板替換輸出

      1. 讀取頁面信息模板文件

      framework.py示例代碼:

      # 獲取首頁數據 def index(): # 響應狀態 status = "200 OK"; # 響應頭 response_header = [("Server", "PWS2.0")] # 打開模板文件,讀取數據 with open("template/index.html", "r") as file: file_data = file.read()

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      2. 使用模擬數據替換模板變量

      framework.py示例代碼:

      # 獲取首頁數據 def index(): # 響應狀態 status = "200 OK"; # 響應頭 response_header = [("Server", "PWS2.0")] # 1. 打開模板文件,讀取數據 with open("template/index.html", "r") as file: file_data = file.read() # 處理后的數據, 從數據庫查詢 data = time.ctime() # 2. 替換模板文件中的模板遍歷 result = file_data.replace("{%content%}", data) return status, response_header, result

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      3. 小結

      模板替換功能

      打開template目錄下的index.html模板文件,讀取模板文件數據

      把模板文件中的模板變量進行替換

      三:路由列表功能

      1. 路由的介紹

      接著上面程序的判斷場景,假如咱們再處理一個個人中心的動態資源請求非常簡單,再添加一個函數和更加一個分支判斷就可以實現了。

      framework.py 示例代碼:

      # 獲取個人中心數據 def center(): # 響應狀態 status = "200 OK"; # 響應頭 response_header = [("Server", "PWS2.0")] # 打開模板文件,讀取數據 with open("template/center.html", "r") as file: file_data = file.read() # 處理后的數據, 從數據庫查詢 data = time.ctime() # 替換模板文件中的模板遍歷 result = file_data.replace("{%content%}", data) return status, response_header, result # 處理動態資源請求 def handle_request(env): # 獲取動態請求資源路徑 request_path = env["request_path"] print("接收到的動態資源請求:", request_path) if request_path == "/index.html": # 獲取首頁數據 result = index() return result elif request_path == "/center.html": # 獲取個人中心數據 result = center() return result else: # 沒有找到動態資源 result = not_found() return result

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      那如果咱們的框架處理的頁面請求路徑再多一些,比如:5個路徑判斷,大家可能感覺條件分支完全可以勝任,如果是40個甚至更多呢? 如果這是還是用普通的條件分支簡直無法忍受。

      解決辦法: 可以使用路由

      什么是路由?

      路由就是請求的URL到處理函數的映射,也就是說提前把請求的URL和處理函數關聯好。

      路由列表

      這么多的路由如何管理呢, 可以使用一個路由列表進行管理,通過路由列表保存每一個路由。

      2. 在路由列表添加路由

      framework.py 示例代碼:

      # 定義路由列表 route_list = [ ("/index.html", index), ("/center.html", center) ]

      1

      2

      3

      4

      5

      3. 根據用戶請求遍歷路由列表處理用戶請求

      framework.py 示例代碼:

      # 處理動態資源請求 def handle_request(env): # 獲取動態請求資源路徑 request_path = env["request_path"] print("接收到的動態資源請求:", request_path) # 遍歷路由列表,選擇執行的函數 for path, func in route_list: if request_path == path: result = func() return result else: # 沒有找到動態資源 result = not_found() return result # if request_path == "/index.html": # # 獲取首頁數據 # result = index() # return result # elif request_path == "/center.html": # # 獲取個人中心數據 # result = center() # return result # else: # # 沒有找到動態資源 # result = not_found() # return result

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      小結

      路由是請求的URL到處理函數的映射

      路由列表是用來保存每一個設置好的路由

      用戶的動態資源請求通過遍歷路由列表找到對應的處理函數來完成。

      四:裝飾器方式的添加路由

      1. 使用帶有參數的裝飾器添加路由

      前面我們已經實現了路由列表,但是每次添加路由都需要手動添加來完成,接下來我們想要完成路由的自動添加,可以通過裝飾器來實現,在使用裝飾器對處理函數進行裝飾的時候我們需要知道裝飾的函數和那個請求路徑進行關聯,也就是說裝飾器需要接收一個url參數,這樣我們定義的裝飾器是一個帶有參數的裝飾器。

      示例代碼:

      """miniweb框架,負責處理動態資源請求""" import time # 定義路由列表 route_list = [] # 定義帶有參數的裝飾器 def route(path): # 裝飾器 def decorator(func): # 當執行裝飾器裝飾指定函數的時候,把路徑和函數添加到路由列表 route_list.append((path, func)) def inner(): # 執行指定函數 return func() return inner # 返回裝飾器 return decorator # 獲取首頁數據 @route("/index.html") def index(): # 響應狀態 status = "200 OK"; # 響應頭 response_header = [("Server", "PWS2.0")] # 打開模板文件,讀取數據 with open("template/index.html", "r") as file: file_data = file.read() # 處理后的數據, 從數據庫查詢 data = time.ctime() # 替換模板文件中的模板遍歷 result = file_data.replace("{%content%}", data) return status, response_header, result # 獲取個人中心數據 @route("/center.html") def center(): # 響應狀態 status = "200 OK"; # 響應頭 response_header = [("Server", "PWS2.0")] # 打開模板文件,讀取數據 with open("template/center.html", "r") as file: file_data = file.read() # 處理后的數據, 從數據庫查詢 data = time.ctime() # 替換模板文件中的模板遍歷 result = file_data.replace("{%content%}", data) return status, response_header, result # 沒有找到動態資源 def not_found(): # 響應狀態 status = "404 Not Found"; # 響應頭 response_header = [("Server", "PWS2.0")] # 處理后的數據 data = "not found" return status, response_header, data # 處理動態資源請求 def handle_request(env): # 獲取動態請求資源路徑 request_path = env["request_path"] print("接收到的動態資源請求:", request_path) # 遍歷路由列表,選擇執行的函數 for path, func in route_list: if request_path == path: result = func() return result else: # 沒有找到動態資源 result = not_found() return result

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      85

      86

      87

      88

      89

      2. 小結

      使用帶有參數的裝飾器對處理函數進行裝飾,并完成路由的添加功能。

      五:日志的使用

      1. logging日志的介紹

      在現實生活中,記錄日志非常重要,比如:銀行轉賬時會有轉賬記錄;飛機飛行過程中,會有個黑盒子(飛行數據記錄器)記錄著飛機的飛行過程,那在咱們python程序中想要記錄程序在運行時所產生的日志信息,怎么做呢?

      可以使用 logging 這個包來完成

      記錄程序日志信息的目的是:

      可以很方便的了解程序的運行情況

      可以分析用戶的操作行為、喜好等信息

      方便開發人員檢查bug

      2. logging日志級別介紹

      日志等級可以分為5個,從低到高分別是:

      DEBUG

      INFO

      WARNING

      ERROR

      CRITICAL

      日志等級說明:

      DEBUG:程序調試bug時使用

      INFO:程序正常運行時使用

      WARNING:程序未按預期運行時使用,但并不是錯誤,如:用戶登錄密碼錯誤

      ERROR:程序出錯誤時使用,如:IO操作失敗

      CRITICAL:特別嚴重的問題,導致程序不能再繼續運行時使用,如:磁盤空間為空,一般很少使用

      默認的是WARNING等級,當在WARNING或WARNING之上等級的才記錄日志信息。

      日志等級從低到高的順序是: DEBUG < INFO < WARNING < ERROR < CRITICAL

      3. logging日志的使用

      在 logging 包中記錄日志的方式有兩種:

      輸出到控制臺

      保存到日志文件

      日志信息輸出到控制臺的示例代碼:

      import logging logging.debug('這是一個debug級別的日志信息') logging.info('這是一個info級別的日志信息') logging.warning('這是一個warning級別的日志信息') logging.error('這是一個error級別的日志信息') logging.critical('這是一個critical級別的日志信息')

      1

      2

      3

      4

      5

      6

      7

      運行結果:

      WARNING:root:這是一個warning級別的日志信息 ERROR:root:這是一個error級別的日志信息 CRITICAL:root:這是一個critical級別的日志信息

      1

      2

      3

      說明:

      日志信息只顯示了大于等于WARNING級別的日志,這說明默認的日志級別設置為WARNING

      logging日志等級和輸出格式的設置:

      import logging # 設置日志等級和輸出日志格式 logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s') logging.debug('這是一個debug級別的日志信息') logging.info('這是一個info級別的日志信息') logging.warning('這是一個warning級別的日志信息') logging.error('這是一個error級別的日志信息') logging.critical('這是一個critical級別的日志信息')

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      運行結果:

      2019-02-13 20:41:33,080 - hello.py[line:6] - DEBUG: 這是一個debug級別的日志信息 2019-02-13 20:41:33,080 - hello.py[line:7] - INFO: 這是一個info級別的日志信息 2019-02-13 20:41:33,080 - hello.py[line:8] - WARNING: 這是一個warning級別的日志信息 2019-02-13 20:41:33,080 - hello.py[line:9] - ERROR: 這是一個error級別的日志信息 2019-02-13 20:41:33,080 - hello.py[line:10] - CRITICAL: 這是一個critical級別的日志信息

      1

      2

      3

      4

      5

      代碼說明:

      level 表示設置的日志等級

      format 表示日志的輸出格式, 參數說明:

      %(levelname)s: 打印日志級別名稱 %(filename)s: 打印當前執行程序名 %(lineno)d: 打印日志的當前行號 %(asctime)s: 打印日志的時間 %(message)s: 打印日志信息

      1

      2

      3

      4

      5

      日志信息保存到日志文件的示例代碼:

      import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s', filename="log.txt", filemode="w") logging.debug('這是一個debug級別的日志信息') logging.info('這是一個info級別的日志信息') logging.warning('這是一個warning級別的日志信息') logging.error('這是一個error級別的日志信息') logging.critical('這是一個critical級別的日志信息')

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      運行結果:

      4. logging日志在mini-web項目中應用

      web.py 程序使用logging日志示例:

      程序入口模塊設置logging日志的設置

      import socket import threading import sys import framework import logging # logging日志的配置 logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s', filename="log.txt", filemode="w")

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      INFO級別的日志輸出,示例代碼:

      # 判斷是否是動態資源請求 if request_path.endswith(".html"): """這里是動態資源請求,把請求信息交給框架處理""" logging.info("動態資源請求:" + request_path) ... else: """這里是靜態資源請求""" logging.info("靜態資源請求:" + request_path) ...

      1

      2

      3

      4

      5

      6

      7

      8

      9

      WARNING級別的日志輸出,示例代碼:

      # 獲取命令行參數判斷長度 if len(sys.argv) != 2: print("執行命令如下: python3 xxx.py 9000") logging.warning("用戶在命令行啟動程序參數個數不正確!") return # 判斷端口號是否是數字 if not sys.argv[1].isdigit(): print("執行命令如下: python3 xxx.py 9000") logging.warning("用戶在命令行啟動程序參數不是數字字符串!") return

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      framework.py 程序使用logging日志示例:

      ERROR級別的日志輸出,示例代碼:

      # 處理動態資源請求 def handle_request(env): # 獲取動態請求資源路徑 request_path = env["request_path"] print("接收到的動態資源請求:", request_path) # 遍歷路由列表,選擇執行的函數 for path, func in route_list: if request_path == path: result = func() return result else: logging.error("沒有設置相應的路由:" + request_path) # 沒有找到動態資源 result = not_found() return result

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      說明:

      logging日志配置信息在程序入口模塊設置一次,整個程序都可以生效。

      logging.basicConfig 表示 logging 日志配置操作

      5. 小結

      記錄python程序中日志信息使用 logging 包來完成

      logging日志等級有5個:

      DEBUG INFO WARNING ERROR CRITICAL

      1

      2

      3

      4

      5

      打印(記錄)日志的函數有5個:

      logging.debug函數, 表示: 打印(記錄)DEBUG級別的日志信息 logging.info函數, 表示: 打印(記錄)INFO級別的日志信息 logging.warning函數, 表示: 打印(記錄)WARNING級別的日志信息 logging.error函數, 表示: 打印(記錄)ERROR級別的日志信息 logging.critical函數, 表示: 打印(記錄)CRITICAL級別的日志信息

      1

      2

      3

      4

      5

      Python web前端

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:設計模式的C語言應用-表驅動模式
      下一篇:優化安全關鍵系統中的警報器放置
      相關文章
      国产亚洲福利精品一区| 亚洲美女中文字幕| 亚洲区日韩区无码区| 亚洲六月丁香婷婷综合| 久久亚洲伊人中字综合精品| 国产精品亚洲а∨无码播放不卡 | 亚洲色婷婷一区二区三区| 国产国拍亚洲精品福利 | 亚洲国产成人久久精品99| 午夜亚洲国产精品福利| 亚洲爆乳成av人在线视菜奈实| 亚洲色丰满少妇高潮18p| 亚洲国产成人久久精品大牛影视| 亚洲人成色99999在线观看| 亚洲日产乱码一二三区别| 亚洲国产成人久久精品软件| 日本亚洲欧美色视频在线播放| 狠狠综合亚洲综合亚洲色| 亚洲成a人片在线观看国产| 国产成人亚洲综合| 国产亚洲人成网站在线观看不卡| 久久精品国产69国产精品亚洲| 久久国产精品亚洲综合| 97亚洲熟妇自偷自拍另类图片| 亚洲福利秒拍一区二区| 亚洲av无码片区一区二区三区| 亚洲男人天堂2022| 日韩色日韩视频亚洲网站| 亚洲男人的天堂在线va拉文| 伊伊人成亚洲综合人网7777| 亚洲国产精品一区二区久久hs| 亚洲AV日韩精品久久久久久| 亚洲自偷自拍另类图片二区| 亚洲人成网男女大片在线播放| 亚洲欧美一区二区三区日产| 久久久久亚洲国产AV麻豆| 精品国产人成亚洲区| 久久综合日韩亚洲精品色| 亚洲小视频在线播放| 亚洲另类自拍丝袜第五页 | 91亚洲国产成人精品下载|