zoukankan      html  css  js  c++  java
  • WSGI服务器

      1 import re
      2 from pymysql import connect
      3 import urllib.parse
      4 import logging
      5 
      6 
      7 URL_FUNC_DICT = dict()
      8 
      9 def open_mysql():
     10     # 创建connect连接
     11     conn = connect(host='localhost',port=3306,user='root',password='m',database='stock',charset='utf8')
     12     # 获得cursor对象
     13     cs = conn.cursor()
     14     return conn, cs
     15 
     16 def close_mysql(conn, cs):
     17     # 关闭连接、对象
     18     cs.close()
     19     conn.close()
     20 
     21 def route(path_info):
     22     '''装饰器:添加方法-路径到字典'''
     23     def set_func(func):
     24         URL_FUNC_DICT[path_info] = func
     25         def call_func(*args, **kwargs):
     26             return func(*args, **kwargs)
     27         return call_func
     28     return set_func
     29 
     30 @route(r"/index.html")
     31 def index(ret):
     32     # 打开、读取网页
     33     with open("./templates/index.html", encoding="utf-8") as f:
     34         content = f.read()
     35     # 打开数据库
     36     conn, cs = open_mysql()
     37     # 执行sql语句
     38     cs.execute("select * from info;")
     39     # 读取数据库数据
     40     stock_infos = cs.fetchall()
     41     # 关闭数据库
     42     close_mysql(conn, cs)
     43     # 数据库数据替换模板数据
     44     tr_template = """<tr>
     45         <td>%s</td>
     46         <td>%s</td>
     47         <td>%s</td>
     48         <td>%s</td>
     49         <td>%s</td>
     50         <td>%s</td>
     51         <td>%s</td>
     52         <td>%s</td>
     53         <td>
     54             <input type="button" value="添加" id="toAdd" name="toAdd" systemidvaule="%s">
     55         </td>
     56         </tr>
     57     """
     58     html = ""
     59     for line_info in stock_infos:
     60         html += tr_template % (line_info[0],line_info[1],line_info[2],line_info[3],line_info[4],line_info[5],line_info[6],line_info[7], line_info[1])
     61     return re.sub(r"{%content%}", html, content)
     62 
     63 @route(r"/center.html")
     64 def center(ret):
     65     # 打开读取网页
     66     with open("./templates/center.html", encoding="utf-8") as f:
     67         content = f.read()
     68     # 打开数据库
     69     conn, cs = open_mysql()
     70     # 执行sql语句
     71     cs.execute("select i.code, i.short, i.chg, i.turnover, i.price, i.highs, f.note_info from info as i inner join focus as f on i.id = f.info_id;")
     72     # 读取sql语句结果
     73     stock_infos = cs.fetchall()
     74     # 关闭数据库
     75     close_mysql(conn, cs)
     76     tr_template = """
     77         <tr>
     78             <td>%s</td>
     79             <td>%s</td>
     80             <td>%s</td>
     81             <td>%s</td>
     82             <td>%s</td>
     83             <td>%s</td>
     84             <td>%s</td>
     85             <td>
     86                 <a type="button" class="btn btn-default btn-xs" href="/update/%s.html"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> 修改 </a>
     87             </td>
     88             <td>
     89                 <input type="button" value="删除" id="toDel" name="toDel" systemidvaule="%s">
     90             </td>
     91         </tr>
     92     """
     93     # 用数据库内容替换模板数据
     94     html = ""
     95     for stock_info in stock_infos:
     96         html += tr_template % (stock_info[0], stock_info[1], stock_info[2], stock_info[3],stock_info[4], stock_info[5], stock_info[6], stock_info[0], stock_info[0])
     97     return re.sub(r"{%content%}", html, content)
     98 
     99 @route(r"^/add/(d+).html$")
    100 def add_focus(ret):
    101     '''添加股票'''
    102     # 获取股票代码
    103     stock_code = ret.group(1)
    104     # 打开数据库,查询股票代码
    105     conn, cs = open_mysql()
    106     sql = "select * from info where code = %s;"
    107     cs.execute(sql, (stock_code,))
    108     # 股票代码不在数据库中
    109     if not cs.fetchall():
    110         # 返回提示
    111         close_mysql(conn, cs)
    112         return "没有这只股票代码,请收下留情。。"
    113     # 判断股票代码是否已存在于focus表数据库中
    114     sql = "select * from info as i inner join focus as f on i.id = f.info_id where i.code = %s"
    115     cs.execute(sql, (stock_code,))
    116     # 已存在于focus表
    117     if cs.fetchall():
    118         close_mysql(conn, cs)
    119         return "已成功关注,请勿重复关注。。"
    120     # 不存在于focu表
    121     # 执行sql语句添加股票代码到focus表
    122     sql = "insert into focus(info_id) select id from info where code = %s;"
    123     cs.execute(sql, (stock_code))
    124     conn.commit()
    125     # 关闭数据库
    126     close_mysql(conn, cs)
    127     return "关注成功。。"
    128 
    129 @route(r"^/del/(d+).html$")
    130 def del_focus(ret):
    131     '''取消关注股票'''
    132     stock_code = ret.group(1)
    133     print(stock_code)
    134     conn, cs = open_mysql()
    135     sql = "select * from focus as f inner join info as i on i.id = f.info_id where i.code = %s;"
    136     cs.execute(sql, (stock_code,))
    137     # 股票代码不存在于focus表
    138     if not cs.fetchall():
    139         close_mysql(conn, cs)
    140         return "未曾关注,谈何取消。。"
    141     sql = "delete from focus where info_id = (select id from info where code = %s);"
    142     cs.execute(sql, (stock_code,))
    143     conn.commit()
    144     close_mysql(conn, cs)
    145     return "已成功取关注。。"
    146 
    147 @route(r"/update/(d+).html")
    148 def update_info(ret):
    149     '''更新数据'''
    150     # 获取股票代码
    151     stock_code = ret.group(1)
    152     # 打开数据库,查询股票代码
    153     conn, cs = open_mysql()
    154     sql = "select * from info where code = %s;"
    155     cs.execute(sql, (stock_code,))
    156     # 股票代码不在数据库中
    157     if not cs.fetchall():
    158         # 返回提示
    159         close_mysql(conn, cs)
    160         return "没有这只股票代码,请收下留情。。"
    161     # 判断股票代码是否已存在于focus表数据库中
    162     sql = "select * from info as i inner join focus as f on i.id = f.info_id where i.code = %s"
    163     cs.execute(sql, (stock_code,))
    164     # 已存在于focus表
    165     if not cs.fetchall():
    166         close_mysql(conn, cs)
    167         return "没有关注,请勿输入备注。。"
    168     # 打开网页
    169     with open("./templates/update.html", encoding="utf-8") as f:
    170         content = f.read()
    171     # 替换模板,回传数据
    172     content = re.sub(r"{%note_info%}","请输入修改内容", content)
    173     return re.sub(r"{%code%}", stock_code, content)
    174     # return "更新数据成功。。"
    175 
    176 @route(r"/update/(d+)/(.*).html")
    177 def save_update(ret):
    178     stock_code = ret.group(1)
    179     new_info = ret.group(2)
    180     new_info = urllib.parse.unquote(new_info)
    181     # 打开数据库,查询股票代码
    182     conn, cs = open_mysql()
    183     sql = "select * from info where code = %s;"
    184     cs.execute(sql, (stock_code,))
    185     # 股票代码不在数据库中
    186     if not cs.fetchall():
    187         # 返回提示
    188         close_mysql(conn, cs)
    189         return "没有这只股票代码,请收下留情。。"
    190     # 判断股票代码是否已存在于focus表数据库中
    191     sql = "select * from info as i inner join focus as f on i.id = f.info_id where i.code = %s"
    192     cs.execute(sql, (stock_code,))
    193     # 不存在于focu表
    194     if not cs.fetchall():
    195         close_mysql(conn, cs)
    196         return "未曾关注,请勿修改。。"
    197     # 已存在于focus表
    198     # 执行sql语句添加股票代码到focus表
    199     sql = "update focus set note_info=%s where info_id = (select id from info where code=%s);"
    200     cs.execute(sql, (new_info, stock_code))
    201     conn.commit()
    202     # 关闭数据库
    203     close_mysql(conn, cs)
    204     return "修改成功。。"
    205 
    206 def application(env, start_header):
    207     start_header("200 OK", [("Content-type", "text/html;charset=utf-8")])
    208     # 获取请求文件信息
    209     file_name = env["PATH_INFO"]
    210     file_name = urllib.parse.unquote(file_name)
    211     # 日志设定
    212     # 创建logger
    213     logger = logging.getLogger()
    214     logger.setLevel(logging.DEBUG)
    215     # 创建一个handler,用于写入文件
    216     logfile = "./log.txt"
    217     fh = logging.FileHandler(logfile,mode='a')
    218     fh.setLevel(logging.INFO)
    219     # 创建一个handler,用于输出控制台
    220     ch = logging.StreamHandler()
    221     ch.setLevel(logging.WARNING)
    222     # 定义日志输出格式
    223     formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
    224     fh.setFormatter(formatter)
    225     ch.setFormatter(formatter)
    226     # 将logger添加到handler中
    227     logger.addHandler(fh)
    228     logger.addHandler(ch)
    229     logger.info("客户访问:%s" % file_name)
    230     try:
    231         for url, func in URL_FUNC_DICT.items():
    232             ret = re.match(url, file_name)
    233             if ret:
    234                 return func(ret)
    235         else:
    236             logger.warning("请求错误。file(%s) not found" % file_name)
    237             return "请求错误。file(%s) not found" % file_name
    238     except Exception as e:
    239         logger.warning("程序异常。错误信息:%s" % e)
    240         return "请求错误。logger错误信息:%s" % e
      1 import sys
      2 import re
      3 import socket
      4 import multiprocessing
      5 
      6 class WSGIServer(object):
      7     '''服务器运行对象'''
      8     def __init__(self, port, app, static_path):
      9         '''对象初始化'''
     10         # 创建套接字
     11         self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     12         self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
     13         # 绑定端口 IP
     14         self.tcp_server_socket.bind(("", port))
     15         # 设置监听套接字
     16         self.tcp_server_socket.listen(128)
     17         # web框架调用方法
     18         self.application = app
     19         # 静态网页存放地址
     20         self.static_path = static_path
     21 
     22     def client_serve(self, client_socket):
     23         '''为浏览器实现具体服务'''
     24         # 获取浏览器请求
     25         request = client_socket.recv(1024).decode("utf-8")
     26         request_lines = request.splitlines()
     27         # 解析浏览器请求
     28         ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
     29         file_name = ""
     30         if ret:
     31             file_name = ret.group(1)
     32             if file_name == "/":
     33                 file_name = "/index.html"
     34         # print("file_nema:", file_name)
     35         # 如果为静态页面请求(非html请求)
     36         if not file_name.endswith(".html"):
     37             # 打开请求页面
     38             try:
     39                 with open(self.static_path + file_name, "rb") as f:
     40                     response_body = f.read()
     41             # 打开页面失败
     42             except:
     43                 response_body = "file not found"
     44                 response_header = "HTTP/1.1 404 FILE NOT FOUND
    "
     45                 response_header += "
    "
     46                 response = response_header + response_body
     47                 client_socket.send(response.encode("utf-8"))
     48             # 打开页面成功
     49             else:
     50                 response_header = "HTTP/1.1 200 OK
    "
     51                 response_header += "
    "
     52                 response = response_header.encode("utf-8") + response_body
     53                 client_socket.send(response)
     54         # 如果为动态页面请求
     55         else:
     56             env = dict()
     57             env["PATH_INFO"] = file_name
     58             # print(file_name)
     59             # 调用web框架方法,处理页面
     60             response_body = self.application(env, self.set_headers)
     61 
     62             response_header = "HTTP/1.1 %s 
    " % self.status
     63             for header in self.header_list:
     64                 response_header += "%s:%s
    " %(header[0],header[1])
     65             response_header += "
    "
     66 
     67             response = response_header + response_body
     68             client_socket.send(response.encode("utf-8"))
     69         # 关闭套接字
     70         client_socket.close()
     71 
     72     def set_headers(self, status, header_list):
     73         '''存放web框架请求头信息'''
     74         self.status = status
     75         self.header_list = header_list
     76 
     77     def fun_forever(self):
     78         '''服务器对象流程控制'''
     79         while True:
     80             # print("等待浏览器连接")
     81             client_socket, client_addr = self.tcp_server_socket.accept()
     82             # 利用多进程实现多任务操作
     83             # print("创建子线程")
     84             p = multiprocessing.Process(target=self.client_serve, args=(client_socket,))
     85             p.start()
     86             client_socket.close()
     87 
     88 def error_msg():
     89     print("服务器开启失败,请按以下方式输入")
     90     print("python xxx.py 8080 mini_frame:application")
     91 
     92 def main():
     93     '''实现主体流程控制'''
     94     # # 获取服务器端口、web_frame框架地址、方法名
     95     # # 如果程序调用参数为3,输入正确
     96     # if len(sys.argv) == 3:
     97     #     # 参数输入方式正确
     98     #     try:
     99     #         port = int(sys.argv[1])
    100     #         frame_app_name = sys.argv[2]
    101     #     # 参数输入方式错误
    102     #     except:
    103     #         error_msg()
    104     # # 如果不为3,调用方法错误,输出提示
    105     # else:
    106     #     error_msg()
    107     port = 8080
    108     frame_app_name = "mini_frame:application"
    109     # 打开配置文件,获取静态、动态文件夹地址
    110     with open("web_server.conf") as f:
    111         conf_info = eval(f.read())
    112     dynamic_path = conf_info["dynamic_path"]
    113     sys.path.append(dynamic_path)
    114     # 获取框架名、方法名
    115     ret = re.match(r"([^:]+):(.*)", frame_app_name)
    116     if ret:
    117         frame_name = ret.group(1)
    118         app_name = ret.group(2)
    119         # print("app",app_name)
    120     else:
    121         error_msg()
    122     # 导入web_frame框架
    123     frame = __import__(frame_name)
    124     # 导入app方法
    125     app = getattr(frame, app_name)
    126     # print("创建WSGI对象")
    127     # 创建WSGI对象
    128     wsgi_server = WSGIServer(port, app, conf_info["static_path"])
    129     # 调用其run_forever方法,使流程不断运行
    130     wsgi_server.fun_forever()
    131 
    132 if __name__ == "__main__":
    133     main()
  • 相关阅读:
    常见的HTTP状态码(HTTP Status Code)说明
    eclipse tomcat maven热部署
    log4j.properties 详解与配置步骤
    js玩命加载……
    git学习
    vim学习笔记
    Android中在不同activity中进行自定义广播的解析
    Android中本地广播的实现
    Android中自定义广播的实现
    Android中获得网络状况的实现
  • 原文地址:https://www.cnblogs.com/sure-feng/p/10427603.html
Copyright © 2011-2022 走看看