Web框架? 什么是web框架呢?
当用户请求www.baidu.com页面的时候,实质是跟www.baidu.com服务器主机的80端口进行交互。之前都学习了socket编程,会发现www.baidu.com:80本质上就是一个socket服务端程序,浏览器实质上就是一个socket客户端。
可想之前学的web服务器(比如apache,nginx……)我们可以理解为高配版的socket服务端。那我们先用python写个低配版的socket服务端,如下代码:
import socket
def handle_request(client): # 与客户端的交互
buf = client.recv(1024)
client.send('HTTP/1.1 200 OK\r\n\r\n')
client.send('Hello Python!')
def main():
server = socket.socket()
server.bind(('127.0.0.1', 9999))
server.listen(5)
print “server is running 127.0.0.1:9999”
while True:
conn, address = server.accept()
handle_request(conn)
conn.close()
if __name__ == "__main__":
main()
运行上述代码,在主机上访问页面: http://127.0.0.1:9999即可看到hello python!的页面.
- 上述通过socket来实现了其本质,而对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。
服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。
应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。
Web服务端程序和应用端程序怎么配合? Wsgi是什么?
- 不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。这样,服务器程序就需要为不同的框架提供不同的支持。
- 这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。
- 因此,有了一种规范wsgi(web server gateway interface),它定义了web服务端程序和web应用程序之间配合使用的规范,让服务端程序的开发人员专注开发服务端,web应用程序专注于App的开发,这个时候server程序与APP程序可以自由组合,配合使用.
Python自带的支持wsgi的服务端程序库wsgiref
python标准库提供的独立WSGI服务器称为wsgiref。
WSGI对于应用程序有以下标准规定:
- 应用程序必须是一个可调用的对象,因此,应用程序可以是一个函数,一个类。
- 应用程序必须接受两个参数并且要按照位置顺序,分别是environ(环境变量),以及start_response函数(负责将响应的status code,headers写进缓冲区但不返回给客户端)。
- 应用程序返回的结果必须是一个可迭代的对象。
# wsgiref的server端只能支持单线程,因此一般只作测试之用
from wsgiref.simple_server import make_server
def App(environ, start_response):
start_response('200 OK',[('Content-Type', 'text/html')])
return '<h1>hello Westos!</h1>'
if __name__ == "__main__":
server = make_server('127.0.0.1',8888,App)
print "server http on port 8888......"
server.serve_forever()
运行上述代码,在主机上访问页面: http://127.0.0.1:8888 即可看到hello Westos!的页面.
自定义Web框架
正常我们访问某个网站,都会有各自的网站,比如bbs,login或者blog等,那么要实现的功能就是:
- 当用户访问http://127.0.0.1/bbs/执行的为bbs的程序;
- 当用户访问http://127.0.0.1/login/执行的为login的程序;
- 当用户访问http://127.0.0.1/blog/执行的为blog的程序;
- 当用户访问除了给定的页面,其他的访问404报错;
# wsgiref的server端只能支持单线程,因此一般只作测试之用
from wsgiref.simple_server import make_server
def login():
return "login"
def bbs():
return "bbs"
def blog():
return "blog"
def routers():
urlpatterns = (
('/login/', login),
('/bbs/', bbs),
('/blog/', blog),
)
return urlpatterns
def App(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
url = environ['PATH_INFO']
urlpatterns = routers()
fun = None
for item in urlpatterns:
print "item:{}".format(item)
if item[0] == url:
fun = item[1]
break
if fun:
return fun()
else:
return "<h1>404 not found!</h1>"
if __name__ == "__main__":
server = make_server('127.0.0.1', 8886, App)
print "server http on port 8886......"
server.serve_forever()