python miniwebフレームワークの実装
8333 ワード
ユーザーはブラウザを通じてwebサーバーに要求を送信し、サーバーは要求資源によって異なる戻り方式を採用し、ブラウザが要求したのは静的資源で、サーバーは直接応答資源に戻り、ブラウザが要求したのは動的資源で、サーバーは要求をフレームワークに送信し、フレームワークはテンプレートを呼び出し、要求データとテンプレートを結合してサーバーに戻る必要がある.サーバはテンプレートを応答体としてブラウザに送信します.
ブラウザは応答体を読み取り、画像などの静的リソースがあれば、ブラウザは引き続きサーバにリソース要求を送信し、サーバは直接静的リソースに戻り、すべてのリソース要求が完了すると、ブラウザは最終ページをユーザーに返す.
Webサーバの実装
HttpServer.py
シミュレーションflaskフレームワーク
hframe_flask_stock.py
flaskは,アクセラレータファクトリ方式で経路と関数を対応させ,ルーティングリストに組み込む.
使用するデータベースはstock_ですdbは、データベース内のinfoテーブルとfocusテーブルを使用してデータを提供します.
シミュレーションdjangoフレームワーク
djangoフレームワークは、経路と関数の対応関係をルーティングリストに手動で追加します.
自分でフレームワークを簡単に実現することで、pythonサーバやフレームワークをより深く理解することができます.
ブラウザは応答体を読み取り、画像などの静的リソースがあれば、ブラウザは引き続きサーバにリソース要求を送信し、サーバは直接静的リソースに戻り、すべてのリソース要求が完了すると、ブラウザは最終ページをユーザーに返す.
Webサーバの実装
HttpServer.py
import socket
import re
import gevent
import sys
import hframe_flask_stock
from gevent import monkey
monkey.patch_all()
class HttpServer():
# 1
def __init__(self,port=80):
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 3 ,
socket_address = ("", port)
tcp_server_socket.bind(socket_address)
# 4 , 128( )
tcp_server_socket.listen(128)
# 5
self.tcp_server_socket = tcp_server_socket
def start(self):
# 6 ,
while True:
# 7 ,
new_client_socket,ip_port = self.tcp_server_socket.accept()
print(" ")
g1 = gevent.spawn(self.request_handler,new_client_socket)
# ,
# g1.join()
def request_handler(self,new_client_socket):
# 8 ,
recv_data = new_client_socket.recv(1024)
if not recv_data:
print(" ")
new_client_socket.close()
return
#
request_text = recv_data.decode()
print(" ",request_text)
# \r
,
request_list = request_text.split('\r
')
print(" ",request_list)
ret = re.search(r"\s(.*)\s", request_list[0])
#
if not ret:
print(" ")
new_client_socket.close()
return
#
path_info = ret.group(1)
print(" ",path_info)
if path_info == '/':
path_info = '/index.html'
#
env = {
"PATH_INFO": path_info
}
# .xxx .html
if path_info.endswith(".html"):
status, headers, body = hframe_flask_stock.app(env)
#
response_line = "HTTP/1.1 %s\r
" % status
response_head = ""
for header in headers:
response_head += "%s: %s\r
" % header
response_data = response_line + response_head + "\r
" + body
#
response_data = response_data.encode()
new_client_socket.send(response_data)
new_client_socket.close()
else:
# 9
# 9.1
response_line = ""
# 9.2
response_head = "Server:py1.0\r
"
# 9.3
response_blank = "\r
"
# 9.4
# ,
try:
with open("static"+path_info, "rb") as file:
# response_content
response_content = file.read()
except Exception as e:
response_line = "HTTP/1.1 404 Not Found\r
"
response_content = "Error! %s" % str(e)
#
response_content = response_content.encode()
else:
response_line = "HTTP/1.1 200 OK\r
"
finally:
#
response_data = (response_line + response_head + response_blank).encode() + response_content
# 11
new_client_socket.send(response_data)
# 12
new_client_socket.close()
def main():
# 80
# HttpServer
httpserver = HttpServer()
#
httpserver.start()
if __name__ == '__main__':
main()
シミュレーションflaskフレームワーク
hframe_flask_stock.py
flaskは,アクセラレータファクトリ方式で経路と関数を対応させ,ルーティングリストに組み込む.
使用するデータベースはstock_ですdbは、データベース内のinfoテーブルとfocusテーブルを使用してデータを提供します.
import time
import pymysql
#
Env = {}
mysql_connect = pymysql.connect(host='127.0.0.1', port=3306, user='root', db='stock_db', password='mysql',charset='utf8')
cursor = mysql_connect.cursor()
#
def route(url):
def wrapper(func):
Env[url] = func
def inner():
pass
return wrapper
@route("/gettime.html")
def get_time():
return time.ctime()
@route("/index.html")
def get_index():
with open("./template/index.html", 'r') as f:
f_content = f.read()
sql = "select * from info"
cursor.execute(sql)
cursor_content = cursor.fetchall()
# print(str(cursor_content))
mysql_content = ""
for line in cursor_content:
print(line)
data_str = """
%s
%s
%s
%s
%s
%s
%s
%s
""" % line
mysql_content += data_str
f_content = f_content.replace("{%content%}", mysql_content)
return f_content
@route("/center.html")
def get_center():
with open("./template/center.html", 'r') as f:
f_content = f.read()
sql = "select info.code,info.short,info.chg,info.turnover,info.price,info.highs,focus.note_info from info inner join focus on info.id = focus.info_id"
cursor.execute(sql)
mysql_content = ""
for line in cursor.fetchall():
data_str = """
%s
%s
%s
%s
%s
%s
%s
""" % line
mysql_content += data_str
f_content = f_content.replace("{%content%}", mysql_content)
return f_content
def app(env):
# env web
print(" ")
# print("Env",Env)
path_info = env["PATH_INFO"]
if path_info in Env:
return "200 ok", [('Server', 'py1.0')], Env[path_info]()
else:
#
return "404 Not Forund", [('Server','py1.0')], "this is test frame"
# print(get_index())
シミュレーションdjangoフレームワーク
djangoフレームワークは、経路と関数の対応関係をルーティングリストに手動で追加します.
import time
def get_time():
return time.ctime()
def get_index():
with open("./template/index.html", 'r') as f:
f_content = f.read()
mysql_content = " "
f_content = f_content.replace("{%content%}", mysql_content)
return f_content
def get_center():
with open("./template/center.html", 'r') as f:
f_content = f.read()
mysql_content = " "
f_content = f_content.replace("{%content%}", mysql_content)
return f_content
#
Env = {
"/gettime.html": get_time,
"/index.html":get_index,
"/center.html": get_center
}
def app(env):
# env web
print(" ")
path_info = env["PATH_INFO"]
if path_info in Env:
return "200 ok", [('Server', 'py1.0')], Env[path_info]()
else:
#
return "404 Not Forund", [('Server','py1.0')], "this is test frame"
自分でフレームワークを簡単に実現することで、pythonサーバやフレームワークをより深く理解することができます.