In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
Today, I will talk to you about the interaction specification between WSGI-Web server and Python application, which may not be well understood by many people. In order to make you understand better, the editor has summarized the following content for you. I hope you can get something according to this article.
Specification of how WSGI-Web servers interact with Python applications
What is WSGI?
WSGI, which stands for Python Web Server Gateway Interface, is an interface specification that describes how Web servers interact with Python applications. The specification is described in PEP-3333.
This specification acts as a bridge between Web servers and Python applications. For the Web server, WSGI describes how to give the user's request data to the Python application; for the Python application, WSGI describes how to obtain the user's request data and how to return the processing result of the request to the Web server.
WSGI application
Python applications that meet the WSGI specification must be:
A callable object (callable object, such as a function, class, instance that implements the _ _ call__ method)
Accept two parameters provided by WSGI Server:
Environ dictionary, containing environment variables, request data, such as REQUEST_METHOD,PATH_INFO,QUERY_STRING, etc.
Start_response function, the callback function that starts responding to the request, used to send the response status (HTTP status) and response header (HTTP headers)
Returns an iterable object (usually a sequence of bytes) consisting of elements of type bytes, that is, the response body (Response body)
The following is an example of a Python application that conforms to the WSGI specification with functions, classes, and examples that implement the _ _ call__ method:
# callable object is a function def simple_app (environ, start_response): # response status (status code and status information) status = '200 OK' # response body response_body = b "Hello WSGI" # response header, which is a list Each pair of keys must be a tuple response_headers = [('Content-type',' text/plain'), ('Content-Length', str (len (response_body))] # call back the start_response provided by the WSGI server and return the response status and response header start_response (status, response_headers) # return the response body Iterable object composed of bytes type elements return [response_body] # Callable object is a class class AppClass: "callable object is AppClass class Calling method: for body in AppClass (env, start_response): process_body (body) "" def _ init__ (self, environ, start_response): self.environ = environ self.start = start_response def _ iter__ (self): status = '200 OK' response_body = b "Hello WSGI" response_headers = [(' Content-type', 'text/plain'), (' Content-Length', str (len (response_body))] self.start (status) Response_headers) the yield response_body# callable object is a class instance class AnotherAppClass: the "" callable object is an AnotherAppClass class instance Calling method: app = AnotherAppClass () for body in app (env, start_response): process_body (body) "" def _ init__ (self): pass def _ call__ (self, environ, start_response): status = '200 OK' response_body = b "Hello WSGI" response_headers = [(' Content-type', 'text/plain'), (' Content-Length', str (len (response_body))] start_response (status, response_headers) yield response_body
WSGI server
The WSGI server corresponding to the WSGI application needs to do the following:
Receive HTTP request and return HTTP response
Provide environ data and implement the callback function start_response
Call WSGI application and pass in environ,start_response as an argument
The implementation process within the simplified version of WSGI server:
Import os, sysdef unicode_to_wsgi (u): return u.decode ('utf-8') def wsgi_to_bytes (s): return s.encode (' utf-8') # application is a WSGI application, a callable object def run_with_cgi (application): # prepares environ parameter data # contains the data of this HTTP request internally For example, REQUEST_METHOD, PATH_INFO, QUERY_STRING, etc. Environ = {k: unicode_to_wsgi (v) for kcoding v in os.environ.items ()} # WSGI environment variable environ ['wsgi.input'] = sys.stdin.buffer environ [' wsgi.errors'] = sys.stderr environ ['wsgi.version'] = (1, 0) environ [' wsgi.multithread'] = False environ ['wsgi.multiprocess'] = True environ [' wsgi.run_once'] = True if environ.get ('HTTPS') 'off') in (' on','1'): environ ['wsgi.url_scheme'] =' https' else: environ ['wsgi.url_scheme'] =' http' headers_set = [] headers_sent = [] def write (data): out = sys.stdout.buffer if not headers_set: raise AssertionError ("write () before start_response ()") elif not headers_sent: # before sending the response body for the first time Send the existing response header status, response_headers = headers_sent [:] = headers_set out.write (wsgi_to_bytes ('Status:% s'% status)) for header in response_headers: out.write (wsgi_to_bytes ('% s:% s'% header)) out.write (wsgi_to_bytes ('') out.write (data) out.flush () # start_response callback function According to the HTTP status and response_headers # passed by the WSGI application, set the response status and response header def start_response (status, response_headers, exc_info=None): # handle the exception if exc_info: pass headers_set [:] = [status, response_headers] return write # call the WSGI application Pass in the prepared environ (request data) and start_response (start response callback function) result = application (environ, start_response) # handle the response body try: for data in result: if data: write (data) finally: if hasattr (result, 'close'): result.close ()
Middleware
Middleware (middleware) is between the WSGI server and the WSGI application. For WSGI applications it is the equivalent of a WSGI server, and for a WSGI server it is the equivalent of a WSGI application. It is much like a WSGI application. After receiving the request, it does some processing for the request, and at the same time, it can do some processing for the response after receiving the response. So the characteristics of Middleware are:
Be called by WSGI server or other Middleware and return WSGI application
Call the WSGI application, passing in environ and start_response
We demonstrate Middleware with whitelist filtering and response follow-up processing:
From wsgiref.simple_server import make_serverdef app (environ, start_response): # response status (status code and status information) status = '200 OK' # response body response_body = b "Hello WSGI" # response header, which is a list Each pair of keys must be a tuple response_headers = [('Content-type',' text/plain'), ('Content-Length', str (len (response_body))] # call back the start_response provided by the WSGI server and return the response status and response header start_response (status, response_headers) # return the response body Iterable object composed of bytes type elements return [response_body] # middleware class WhitelistMiddleware (object): def _ _ init__ (self, app): self.app = app # when an instance of class # is called Implement whitelist function def _ call__ (self, environ, start_response) according to the HTTP_HOST obtained from the request: ip_addr = environ.get ('HTTP_HOST'). Split (':') [0] if ip_addr not in ('127.0.0.1'): start_response ('403 Forbidden', [(' Content-Type', 'text/plain')] return [baked Forbidden'] return self.app (environ) Start_response) # Middleware class UpperMiddleware (object) for processing response data: def _ _ init__ (self, app): self.app = app # when a class instance is called Convert the content of the response body to uppercase format def _ _ call__ (self, environ, start_response): for data in self.app (environ, start_response): yield data.upper () if _ _ name__ ='_ _ main__': app = UpperMiddleware (WhitelistMiddleware (app)) with make_server (', 8000, app) as httpd: print ("Serving on port 8000...") Httpd.serve_forever ()
The above example is a complete runnable code. The function app is a WSGI application, and WhitelistMiddleware and UpperMiddleware are WSGI Middleware,WSGI servers that use Python's built-in wsgiref module (wsgiref module is a reference implementation of the WSGI specification provided by Python 3, and the WSGI server in wsgiref can be used for development and testing, but not in a production environment).
Some Middleware usage scenarios are given in the WSGI specification, in which the scenario of distributing to different applications according to the request path is the most basic function of an Web Framework. Let's take a look at an example of routing forwarding through Middleware:
From wsgiref.simple_server import make_server# requests path distribution middleware class RouterMiddleware (object): def _ _ init__ (self): # A dictionary that holds the correspondence between path and the application self.path_info = {} def route (self, environ, start_response): application = self.path_info [environ ['PATH_INFO']] return application (environ, start_response) # when the class instance is called Save path and application correspondence def _ _ call__ (self, path): def wrapper (application): self.path_ info [path] = application return wrapperrouter = RouterMiddleware () @ router ('/ hello') # call RouterMiddleware class instance Save path and application correspondence def hello (environ, start_response): status = '200 OK' response_body = b "Hello" response_headers = [(' Content-type', 'text/plain'), (' Content-Length', str (len (response_body))] start_response (status, response_headers) return [response_body] @ router ('/ world') def world (environ) Start_response): status = '200 OK' response_body = baked World` response_headers = [(' Content-type', 'text/plain'), (' Content-Length', str (len (response_body))] start_response (status, response_headers) return [response_body] @ router ('/') def hello_world (environ, start_response): status = '200 OK' response_body = b'Hello World' response_headers = [(' Content-type', 'text/plain') ('Content-Length', str (len (response_body))] start_response (status, response_headers) return [response_body] def app (environ, start_response): return router.route (environ, start_response) if _ _ name__ = =' _ main__': with make_server (', 8000, app) as httpd: print ("Serving on port 8000...") Httpd.serve_forever ()
The WSGI application described by the WSGI interface specification is too low-level and unfriendly to developers. People usually use Web Framework to complete the development of a Web application, and then deploy the Web application on a Web server for the production environment.
Commonly used Python Web Framework:
Django
A fully functional Web framework with a large developer community and rich third-party libraries.
Flask
A micro framework for building smaller applications, API and web services. Is the default choice for any Python web application that does not apply to Django.
Tornado
An asynchronous web framework that natively supports WebSocket.
Bottle
The smaller Web framework, with only one Python file for the entire framework, is a good source learning case.
Commonly used WSGI Web Server:
Gunicorn
Pure Python implementation of the WSGI server, with a very simple configuration and very reasonable default configuration, easy to use.
UWSGI
Based on the uwsgi protocol, the very powerful Web server also supports the Python WSGI protocol. The performance is good, but the configuration is complex.
After reading the above, do you have any further understanding of the specification of how WSGI-Web servers interact with Python applications? If you want to know more knowledge or related content, please follow the industry information channel, thank you for your support.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.