》你知道WSGI吗
其实,我也不是太清楚,但是我知道一丢丢。记得第一份实习,当时用的是tornado,我就想看看这个东东到底是啥玩意,可是,我看了很久很久,始终没看明白!(听说你英语不咋地啊。。。。)落下,不议论。
画了一个分割线,有那么一天,一个牛逼的同事解释了这个东东,茅塞顿开)))===》
》 你不可不知道的Socket
如果你写过socket,对于以下脚本应该非常熟悉,我们写了一个server,然后用一个client访问
-
my_server.py
#coding:utf-8 import socket # Server #create an INET, STREAMing socket serversocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM) #bind the socket to a public host, # and a well-known port serversocket.bind(('localhost', 8082)) #become a server socket serversocket.listen(5) response="""HTTP/1.1 200 OK\r\n Date: Fri, 22 May 2009 06:07:21 GMT\r\n Content-Type: text/html; charset=UTF-8\r\n \r\n <html>\r\n <head></head>\r\n <body>\r\n hello<!--body goes here-->\r\n </body>\r\n </html>\r\n """ while True: client_sock,client_addr = serversocket.accept(); while True: try: recv_mess = client_sock.recv(1024) if not recv_mess: client_sock.close() print recv_mess client_sock.sendall(response) client_sock.close() except Exception as e: client_sock.close() break
-
my_client.py
#coding:utf-8
import socket
s = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
#now connect to the web server on port 80
# - the normal http port
s.connect(("localhost", 8082))
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)
然后 ,你会问这和http有什么关系,好吧,如果这样的话,就只能说你和我一样是白的不能再白的小白了!
如果你在浏览器中访问:http://localhost:8082/, 神奇的事情发生了。自己去看http协议吧 & 。)
》 封装
如果我们这样些后端代码,估计python也快走向没落了。我们变得优雅一点,于是就有了,Django,flask,tornado等(我就用过这几个%)),我们先看一个分装好的类SocketServer下的TCPServer,源代码非常推荐大家看看!!!!
来个流程图
其实我已经没有什么好说的了,但是,我看到这里不知道如何做处理,如何写View。然后我就去看flask的源码,还不能解决,又去看werkzeug中的代码,然后就懂了。其实你看BaseHTTPRequestHandler的handle时就应该有点思路了。没错,就是在handle中加入处理逻辑。
》再来说说这个WSGI
先给个链接:http://www.nowamagic.net/academy/detail/1330310
核心是这段代码:
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return '<h1>Hello, web!</h1>'
其实我们熟悉的django等叫做WebApplication,这个environ是由一个叫做WebServer传给我们的,也是由他完成最后的socket处理。当然还有一个中间件,看装饰器就明白了。
这个environ中是封装好的request,包括路由,请求方法,请求头,body等,start_response会处理请求头,
好吧,语言无力,直接看代码, 非常清晰
def handle_one_request(self):
"""Handle a single HTTP request."""
self.raw_requestline = self.rfile.readline()
if not self.raw_requestline:
self.close_connection = 1
elif self.parse_request():
return self.run_wsgi()
def run_wsgi(self):
if self.headers.get('Expect', '').lower().strip() == '100-continue':
self.wfile.write(b'HTTP/1.1 100 Continue\r\n\r\n')
self.environ = environ = self.make_environ()
headers_set = []
headers_sent = []
def write(data):
assert headers_set, 'write() before start_response'
if not headers_sent:
status, response_headers = headers_sent[:] = headers_set
try:
code, msg = status.split(None, 1)
except ValueError:
code, msg = status, ""
self.send_response(int(code), msg)
header_keys = set()
for key, value in response_headers:
self.send_header(key, value)
key = key.lower()
header_keys.add(key)
if 'content-length' not in header_keys:
self.close_connection = True
self.send_header('Connection', 'close')
if 'server' not in header_keys:
self.send_header('Server', self.version_string())
if 'date' not in header_keys:
self.send_header('Date', self.date_time_string())
self.end_headers()
assert isinstance(data, bytes), 'applications must write bytes'
self.wfile.write(data)
self.wfile.flush()
def start_response(status, response_headers, exc_info=None):
if exc_info:
try:
if headers_sent:
reraise(*exc_info)
finally:
exc_info = None
elif headers_set:
raise AssertionError('Headers already set')
headers_set[:] = [status, response_headers]
return write
def execute(app):
application_iter = app(environ, start_response)
try:
for data in application_iter:
write(data)
if not headers_sent:
write(b'')
finally:
if hasattr(application_iter, 'close'):
application_iter.close()
application_iter = None
try:
execute(self.server.app)
except (socket.error, socket.timeout) as e:
self.connection_dropped(e, environ)
except Exception:
if self.server.passthrough_errors:
raise
from werkzeug.debug.tbtools import get_current_traceback
traceback = get_current_traceback(ignore_system_exceptions=True)
try:
# if we haven't yet sent the headers but they are set
# we roll back to be able to set them again.
if not headers_sent:
del headers_set[:]
execute(InternalServerError())
except Exception:
pass
self.server.log('error', 'Error on request:\n%s',
traceback.plaintext)
》OVER
多看源码,这一部分结束,以后看看模板和ORM
补充:
建了一个qq群:389954854,主要目的是互帮互助,通过交流促进python技术。很多初学者往往不知道如何下手,还等什么,快快加入进来吧!
或者关注微信公众号:python码码有趣的