wsgi和uwsgi,wsgi和asgi_1

  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

  srv = make_server('localhost', 8080, application)

  srv.serve_forever()复制代码

只要3行代码就可以提供wsgi服务器,是不是超级方便,最后来访问测试下浏览器发起一个请求的效果

  以上就是wsgi简介,深入了解wsgi可以熟悉下PEP333

  

相关免费学习推荐:python视频教程

  

以上就是一定要懂WSGI是什么的详细内容,更多请关注盛行IT软件开发工作室其它相关文章!

  

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: