wsgi和uwsgi,wsgi和asgi
python视频教程栏目介绍WSGI。
我写python web好几年了,还是不知道WSGI是什么,也不知道人多不多。很正常,因为作为开发者,你很少需要知道wsgi是什么,你也可以做一个网站。
但是如果你想写你自己的web框架来取乐,你必须学习wsgi。
回过头来看,我们在使用python进行web开发时,通常是基于某种web框架进行开发,比如django或者flask。业务开发完成后,将部署到服务器上,提供外部访问。
这时候你在网上搜一下,他们会告诉你需要gunicorn或者uwsgi进行部署。那么gunicorn和uwsgi是什么呢?
看看这张照片,你就会明白。我在网上找到的。
uwsgi或者gunicorn在这里扮演的角色是web server的角色,web server是软件级的服务器,用来处理浏览器发送的HTTP请求,并将响应结果返回到前端。web框架的主要任务是处理业务逻辑并向Web服务器生成结果,然后Web服务器将结果返回给浏览器。
而web框架和web服务器之间的通信需要遵循一套规范,这就是WSGI。
为什么要制定这样一套规范?标准化的目的是统一标准,方便大家使用。
试想现在我们手机充电的接口都是Type-c,Type-c是一种规范。手机厂商按照这个规格生产手机,充电器厂商按照Type-C的规格生产充电器,不同厂家的手机可以搭配不同厂家的充电器使用。而苹果则有自己的一套规范,最终导致安卓充电器无法给苹果充电。
![
](p9-Jue Jin . byte img.com/tos-cn-I-k3……)那么如何编写一个符合WSGI规范的应用(框架)程序和服务器呢?
如上图所示,左边是web服务器,右边是web框架,或者说应用。
应用程序
WSGI规定应用必须是可调用对象(可调用对象可以是实现__call__的函数、类或实例对象),并且必须接受两个参数。该对象的返回值必须是iterable对象。我们可以写一个最简单的应用例子。
HELLO_WORLD=bHello world!\ndef应用程序(环境,start_response):
状态=200正常
response _ headers=[( Content-type , text/plain)]
Start_response (status,response _ headers)return【hello _ world】复制代码应用程序是一个函数,它必须是一个可调用的对象,然后接收两个参数,即:environ和Start_response。
Environ是一个字典,存储了与HTTP请求相关的一切,比如头、请求参数等。start_response是WSGI Server传递的函数,用于将响应头和状态码传递给服务器。调用start_response函数将响应头和状态码传递给服务器,响应体由应用程序函数返回给服务器。这两个函数提供了完整的http响应。
但是任何实现wsgi的web框架都会有这样一个可调用的对象。
00-1010 WSGI server所做的就是在每次接收到HTTP请求时构建一个environ对象,然后调用application对象,最后将HTTP响应返回给浏览器。
以下是wsgi服务器的完整代码。
import socket import sysfrom io import string io class wsgi server(object):
address_family=套接字。AF_INET
socket_type=套接字。袜子_流
请求队列大小=1
def __init__(自身,服务器地址):
#创建一个监听套接字
self . listen _ socket=listen _ socket=socket . socket(
self.address_family
self.socket_type
)#允许重用相同的地址
listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Bind
listen_socket.bind(server_address) # Activate
listen_socket.listen(self.request_queue_size) # Get server host name and port
host, port = self.listen_socket.getsockname()[:2]
self.server_name = socket.getfqdn(host)
self.server_port = port # Return headers set by Web framework/Web application
self.headers_set = [] def set_app(self, application):
self.application = application def serve_forever(self):
listen_socket = self.listen_socket while True: # New client connection
self.client_connection, client_address = listen_socket.accept() # Handle one request and close the client connection. Then
# loop over to wait for another client connection
self.handle_one_request() def handle_one_request(self):
self.request_data = request_data = self.client_connection.recv(1024) # Print formatted request data a la 'curl -v'
print(''.join( '< {line}\n'.format(line=line) for line in request_data.splitlines()
))
self.parse_request(request_data) # Construct environment dictionary using request data
env = self.get_environ() # It's time to call our application callable and get
# back a result that will become HTTP response body
result = self.application(env, self.start_response) # Construct a response and send it back to the client
self.finish_response(result) def parse_request(self, text):
request_line = text.splitlines()[0]
request_line = request_line.rstrip('\r\n') # Break down the request line into components
(self.request_method, # GET
self.path, # /hello
self.request_version # HTTP/1.1
) = request_line.split() def get_environ(self):
env = {} # The following code snippet does not follow PEP8 conventions
# but it's formatted the way it is for demonstration purposes
# to emphasize the required variables and their values
#
# Required WSGI variables
env['wsgi.version'] = (1, 0)
env['wsgi.url_scheme'] = 'http'
env['wsgi.input'] = StringIO.StringIO(self.request_data)
env['wsgi.errors'] = sys.stderr
env['wsgi.multithread'] = False
env['wsgi.multiprocess'] = False
env['wsgi.run_once'] = False
# Required CGI variables
env['REQUEST_METHOD'] = self.request_method # GET
env['PATH_INFO'] = self.path # /hello
env['SERVER_NAME'] = self.server_name # localhost
env['SERVER_PORT'] = str(self.server_port) # 8888
return env def start_response(self, status, response_headers, exc_info=None):
# Add necessary server headers
server_headers = [
('Date', 'Tue, 31 Mar 2015 12:54:48 GMT'),
('Server', 'WSGIServer 0.2'),
]
self.headers_set = [status, response_headers + server_headers] # To adhere to WSGI specification the start_response must return
# a 'write' callable. We simplicity's sake we'll ignore that detail
# for now.
# return self.finish_response
def finish_response(self, result):
try:
status, response_headers = self.headers_set
response = 'HTTP/1.1 {status}\r\n'.format(status=status) for header in response_headers:
response += '{0}: {1}\r\n'.format(*header)
response += '\r\n'
for data in result:
response += data # Print formatted response data a la 'curl -v'
print(''.join( '> {line}\n'.format(line=line) for line in response.splitlines()
))
self.client_connection.sendall(response) finally:
self.client_connection.close()
SERVER_ADDRESS = (HOST, PORT) = 'localhost', 8080def make_server(server_address, application):
server = WSGIServer(server_address)
server.set_app(application) return serverif __name__ == '__main__':
httpd = make_server(SERVER_ADDRESS, application)
print('WSGIServer: Serving HTTP on port {port} ...\n'.format(port=PORT))
httpd.serve_forever()复制代码当然,如果只是写个用于开发环境用的server,用不着这么麻烦自己造轮子,因为python内置模块中就提供有 wsgi server 的功能。
from wsgiref.simple_server import make_server只要3行代码就可以提供wsgi服务器,是不是超级方便,最后来访问测试下浏览器发起一个请求的效果srv = make_server('localhost', 8080, application)
srv.serve_forever()复制代码
以上就是wsgi简介,深入了解wsgi可以熟悉下PEP333
相关免费学习推荐:python视频教程以上就是一定要懂WSGI是什么的详细内容,更多请关注盛行IT软件开发工作室其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。