Table of Contents
06WSGI
07服务器支持WSGI
08服务器传递需要的字典参数
09 框架获取页面模板数据
10 添加配置文件、shell功能
简单服务器背景知识
02面向对象服务器
需要http协议的web服务器
03动态解析
回应的时候不止直接返回header+文件
Body中返回变量的字符串-->解耦,调用web框架(负责逻辑)
04
动态的网站是实时生成的
05 将web服务器和逻辑处理分开
Web框架写完login()方法
在服务器import web_frame
Body= web_frame.login()—这一部分依然没有解耦
需要只调用一个函数
在web_frame中定义application函数
服务器将文件名传入application,用body接收返回值
Application根据文件名自己调用
06WSGI动态请求对应框架中的函数
使用著名服务器Nginx等时,不能在已有服务器中导入自己的模块,如何使自己写的框架被服务器支持?
要根据协议(WSGI)来写框架(Flask、Django等)
WSGI规定浏览器请求内容,应返回数据:header+body
WSGI接口定义,要求开发者实现application函数,响应HTTP请求:
def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return ' Hello, web!' |
参数:environ字典,start_response函数的引用(函数名)
start_response是服务器定义的函数,可以通过这个引用调用此函数
header通过调用start_response参数传递给服务器
Body直接用return返回
07服务器支持WSGI调用函数运走了一份header,我再return他一个body
服务器把header和body加起来
调用start_response时传入参数:1.状态码 2.元组列表,其中每个元组包括response需要的k-v(对应一行信息)
服务器取出框架通过start_response传来的headers实例属性:
for temp in self.headers: header+=”%s:%s\r\n” % (temp[0], temp[1]) |
框架需要告诉服务器用了什么编码语音(放在'Content-Type后面)
服务器版本:Server不应该由框架决定、传递,在服务器中加
env=dict()目前还是空字典
需要访问不同的py,返回不同页面,则使用它,接收的filename是字符串
服务器 env[‘PATH_INFO’]=file_name |
框架 filename=env[‘PATH_INFO’] |
将frame文件单独放一个文件夹dynamic,新建__init__.py作为包,可被import
import dynamic.mini_frame #调用 dynamic.mini_frame |
原本框架接收application参数后只是调用对应函数返回值,现需改成页面数据:
可直接return含大段html的字符串,这时link引用的css和js还无法获取
服务器接收到. css等静态文件需要去static文件夹找
f=open(“./static”+filename,”rb”) |
框架返回时读文件返回,而不要直接返回html字符串:
with open(“./templates/index.html”) as f: content=f.read() return content |
如果打开../templates/index.html(相对路径上一级)则无法找到,因为运行的是服务器文件,所有路径都从运行py开始算,不管打开文件的代码是不是在其他包内
一般情况下,服务器和框架是分开的,框架作为可导入的包,服务器加载框架中的.py,框架读取templates中的html文件,并作为字符串返回给服务器
10 添加配置文件、shell功能需求:能否改端口、不修改服务器支撑其他框架
给程序传参:
python3 web_server.py 7788 mini_frame:application |
import sys print(sys.argv) |
接收到参数[‘’test.py,‘7788’,’ mini_frame’]是字符串,不是数字 |
在服务器中:
import sys def main(): if len(sys.argv)==3: try: port=int(sys.argv[1]) except Exception as ret: print(“端口应该为数字”) return else: print(“运行格式:python3 xxxx.py 7890 mini_frame:application”) return wsgi_server=WSGIServer(port) wsgi_server.run_forever() |
class WSGIServer(object): def __init__(self,port): self.tcp_server_socket.bind(“”,port) |
指定模块运行,原先导入了dynamic.mini_frame,但应该是通用的,故作为参数
python3 web_server.py 7788 mini_frame:application |
如何找到该函数:在获取该参数后import,它把直接写的作为模块名而非变量解析,但__import__()可以放变量,返回的对象标记着导入的这个模块, 则getattr返回值指向该模块application
sys.path.append()可添加系统环境路径
frame_app_name=sys.argv[2] re.match(r”({[^:]+}):({.*})”, frame_app_name) #前半部分不是冒号的至少有一个 if ret: frame_name=ret.ret.group(1) app_name=ret.ret.group(1) else: print(“运行格式:python3 xxxx.py 7890 mini_frame:application”) sys.path.append(“./dynamic”) frame=__import__(frame_name) app=getattr(frame,appn_name)
wsgi_server=WSGIServer(port,app) |
使用时
self.application=app body=self.application(env,self.set_response_header) |
解耦不够彻底:
所有静态文件都在static文件夹打开 模块要放在./dynamic支持配置文件:
创建web_server.conf
存储静态文件和框架加载路径
{ "static_path":"./static", "synamic_path":"./dynamic" } |
在服务器中读取文件字符串,转成字典
with open("./web_server.conf") as f: conf_info=eval(f.read())#eval转成字典 sys.path.append(conf_info['dynamic_path'])
wsgi_server=WSGIServer(port,app,conf_info['static_path']) |
#使用
self.static_path=static_path#init中 f=open(self.static_path+filename,"rb") |
shell脚本(放Linux命令):vim run.sh
python3 web_server.py 7890 miniframe:application |
添加可执行权限x:
chmod +x run.sh ./run.sh |
添加readme.txt:
运行方式./run.sh或python3 web_server.py 7890 miniframe:application
version等
lagoon_lala 原创文章 95获赞 139访问量 55万+ 关注 他的留言板 展开阅读全文