内容简介:下面图来自网上:pep-3333建议在Web服务器和Web应用程序/Web框架之家建立一种简单统一的接口规范, 即Python Web服务器网关接口(简称WSGI)。以确保Web应用程序在不同的Web服务器之间具有可移植性。代码部分参考的是
下面图来自网上:
WSGI
为什么需要建立WSGI规范
pep-3333建议在Web服务器和Web应用程序/Web框架之家建立一种简单统一的接口规范, 即Python Web服务器网关接口(简称WSGI)。以确保Web应用程序在不同的Web服务器之间具有可移植性。
参考资料
编写代码
代码部分参考的是 手撸个简单的 python web 框架教程 , 我觉得这个 python 童鞋讲的挺好。
# wsgi_demo.py import pprint # 导入python内置的wsgi server from wsgiref.simple_server import make_server def application(environ, start_response): """ :param environ: 包含一些特定的WSGI环境信息的字典, 由WSGI服务器提供 :param start_response: 生成WSGI响应的回掉函数, 接受两个必要的位置参数和一个可选参数。status,response_headers和 exc_info :return: 响应体的的迭代器 """ pprint.pprint(environ) status = '200 ok' response_headers = [('Content-type', 'text/html;charset=utf8')] start_response(status, response_headers) return ['<h1>Hello, web!</h1>'.encode()] if __name__ == '__main__': httpd = make_server('0.0.0.0', 5000, application) httpd.serve_forever() 复制代码
通过命令行跑起这个server.
python wsgi_demo.py 复制代码
通过另外一个命令行使用curl链接:
~$ curl http://0.0.0.0:5000/ <h1>Hello, web!</h1> 复制代码
常用的environ
environ字典被用来包含这些CGI环境变量。 关于理解CGI/WSGI/uWSGI可以看看这个解释 tornado cgi wsgi uwsgi之间的关系?
1. REQUEST_METHOD HTTP的请求方式,比如 "GET" 或者 "POST"。这个参数永远不可能是空字符串,故必须指定。 2. PATH_INFO URL请求中‘路径’(‘path’)的其余部分,指定请求的目标在应用程序内部的虚拟位置。如果请求的目标是应用程序根目录并且末尾没有'/'符号结尾的话,那么PATH_INFO可能为空字符串 。 3. QUERY_STRING URL请求中紧跟在“?”后面的那部分,它可以为空或不存在。 4. CONTENT_TYPE HTTP请求中Content-Type字段包含的所有内容,它可以为空或不存在。 5. HTTP_ 变量组 这组变量对应着客户端提供的HTTP请求报头(即那些名字以 “HTTP_” 开头的变量) ... 复制代码
我们其实上面通过
pprint.pprint(environ) 复制代码
可以查看到里面所包含的信息。
{ 'Apple_PubSub_Socket_Render':'/private/tmp/com.apple.launchd.9BSE0tnnTO/Render', 'CLICOLOR': '1', 'COLORFGBG': '7;0', 'COLORTERM': 'truecolor', 'CONTENT_LENGTH': '', 'CONTENT_TYPE': 'text/plain', 'FLUTTER_STORAGE_BASE_URL': 'https://storage.flutter-io.cn', 'GATEWAY_INTERFACE': 'CGI/1.1', 'GOBIN': '/Users/xx/Documents/goBin', 'GOPATH': '/Users/xx/Documents/goWorkPlace', 'GOROOT': '/usr/local/go', 'HOME': '/Users/xx', 'HTTP_ACCEPT': '*/*', 'HTTP_HOST': '0.0.0.0:5000', 'HTTP_USER_AGENT': 'curl/7.54.0', 'ITERM_PROFILE': 'Default', 'ITERM_SESSION_ID': 'w0t0p0:D66287F5-65FC-4141-94AC-06A1B3CBEAE4', 'LANG': 'zh_CN.UTF-8', 'LOGNAME': 'xx', 'LSCOLORS': 'exfxhxhxgxhxhxgxgxbxbx', 'PATH': '/Users/xx/.local/share/virtualenvs/flask-demo-MqfCTpGB/bin:/Users/xx/Documents/flutter/bin:/Users/xx/.pyenv/plugins/pyenv-virtualenv/shims:/Users/xx/.pyenv/plugins/pyenv-virtualenv/shims:/Users/xx/.pyenv/shims:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/Users/xx/.local/bin:/usr/local/go/bin:/Users/xx/Documents/goBin', 'PATH_INFO': '/', 'PIPENV_ACTIVE': '1', 'PIP_DISABLE_PIP_VERSION_CHECK': '1', 'PIP_PYTHON_PATH': '/Users/xx/.pyenv/versions/3.6.0/bin/python3.6', 'PS1': '(flask-demo) \\[\\033[01;33m\\]\\u \\W\\$\\[\\033[00m\\] ', 'PUB_HOSTED_URL': 'https://pub.flutter-io.cn', 'PWD': '/Users/xx/Documents/GitHub/flask-demo', 'PYENV_SHELL': 'bash', 'PYENV_VIRTUALENV_INIT': '1', 'PYTHONDONTWRITEBYTECODE': '1', 'QUERY_STRING': '', 'REMOTE_ADDR': '127.0.0.1', 'REMOTE_HOST': '', 'REQUEST_METHOD': 'GET', 'SCRIPT_NAME': '', 'SERVER_NAME': 'XxdeMacBook-Pro.local', 'SERVER_PORT': '5000', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'WSGIServer/0.2', 'SHELL': '/bin/bash', 'SHLVL': '2', 'SSH_AUTH_SOCK': '/private/tmp/com.apple.launchd.qMWayGCpdP/Listeners', 'TERM': 'xterm-256color', 'TERM_PROGRAM': 'iTerm.app', 'TERM_PROGRAM_VERSION': '3.2.0', 'TERM_SESSION_ID': 'w0t0p0:D66287F5-65FC-4141-94AC-06A1B3CBEAE4', 'TMPDIR': '/var/folders/6g/kjvjmf8j59j2tf2mm360dqjm0000gn/T/', 'USER': 'xx', 'VIRTUAL_ENV': '/Users/xx/.local/share/virtualenvs/flask-demo-MqfCTpGB', 'XPC_FLAGS': '0x0', 'XPC_SERVICE_NAME': '0', '_': '/Users/xx/.local/share/virtualenvs/flask-demo-MqfCTpGB/bin/python', '__CF_USER_TEXT_ENCODING': '0x1F5:0x19:0x34', 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>, 'wsgi.input': <_io.BufferedReader name=6>, 'wsgi.multiprocess': False, 'wsgi.multithread': True, 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.version': (1, 0) } 复制代码
在application里面我们通过environ获得我们需要的很多参数, 比如请求的查询字符串等。
封装Request对象
# request.py from six.moves import urllib class Request(object): """接受environ参数, 然后一些子函数供外界使用去获取需要的值""" def __init__(self, environ): self.environ = environ def args(self): """ 把查询参数转成字典形式 """ get_arguments = urllib.parse.parse_qs( self.environ['QUERY_STRING'] ) return {k: v[0] for k, v in get_arguments.items()} def path(self): return self.environ['PATH_INFO'] 复制代码
封装Response对象
# response.py import http.client from six.moves import urllib from wsgiref.headers import Headers class Response(object): """返回内容, 状态码, 字符编码, 返回类型等""" def __init__(self, response=None, status=200, charset='utf-8', content_type='text/html'): self.response = [] if response is None else response self.charset = charset self.headers = Headers() content_type = '{content_type}; charset={charset}'.format( content_type=content_type, charset=charset) self.headers.add_header('content-type', content_type) self._status = status @property def status(self): status_string = http.client.responses.get(self._status, 'UNKNOWN') return '{status} {status_string}'.format( status=self._status, status_string=status_string) def __iter__(self): for val in self.response: if isinstance(val, bytes): yield val else: yield val.encode(self.charset) 复制代码
装饰器函数
# transfer.py from request import Request def request_response_application(func): """把WSGI 函数转换成使用Request/Response 对象""" def application(environ, start_response): request = Request(environ) response = func(request) start_response( response.status, response.headers.items() ) return iter(response) return application 复制代码
改版后的demo
# wsgi_demo.py import pprint # 导入python内置的wsgi server from wsgiref.simple_server import make_server from transfer import request_response_application from response import Response @request_response_application def application(request): # 获取查询字符串中的 name name = request.args().get('name', 'default_name') return Response(['<h1>hello {name}</h1>'.format(name=name)]) if __name__ == '__main__': httpd = make_server('0.0.0.0', 5000, application) httpd.serve_forever() 复制代码
测试demo
python wsgi_demo.py 复制代码
默认情况:
~$ curl http://0.0.0.0:5000/ <h1>hello default_name</h1> 复制代码
带有name的查询字符串
~$ curl http://0.0.0.0:5000/demo?name=kobe <h1>hello kobe</h1> 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
编写可读代码的艺术
Boswell, D.、Foucher, T. / 尹哲、郑秀雯 / 机械工业出版社 / 2012-7-10 / 59.00元
细节决定成败,思路清晰、言简意赅的代码让程序员一目了然;而格式凌乱、拖沓冗长的代码让程序员一头雾水。除了可以正确运行以外,优秀的代码必须具备良好的可读性,编写的代码要使其他人能在最短的时间内理解才行。本书旨在强调代码对人的友好性和可读性。 本书关注编码的细节,总结了很多提高代码可读性的小技巧,看似都微不足道,但是对于整个软件系统的开发而言,它们与宏观的架构决策、设计思想、指导原则同样重要。编......一起来看看 《编写可读代码的艺术》 这本书的介绍吧!