在Python3.0中处理web请求3-多线程
来源:互联网 发布:某市优化投资环境 编辑:程序博客网 时间:2024/06/04 18:36
继续研究Python3进行处理web请求。在第一篇文章的Hello World程序中,是没有进行多线程处理的,导致的情况是当第一个人执行了一个操作,如果这个操作所需要的时间比较长,那么其他人就需要等他执行完后才能访问,这是非常不符合逻辑的,我看了下源码,HTTPServer确实没有进行任何线程处理,若运行以下代码:
#!coding=UTF-8from http.server import HTTPServer,BaseHTTPRequestHandlerimport io,shutil,timeclass MyHttpHandler(BaseHTTPRequestHandler): def do_GET(self): print(self.path) if self.path=='/':time.sleep(5) print(self.path) r_str="Hello World"; enc="UTF-8" encoded = ''.join(r_str).encode(enc) f = io.BytesIO() f.write(encoded) f.seek(0) self.send_response(200) self.send_header("Content-type", "text/html; charset=%s" % enc) self.send_header("Content-Length", str(len(encoded))) self.end_headers() shutil.copyfileobj(f,self.wfile)httpd=HTTPServer(('',8080),MyHttpHandler)print("Server started on 127.0.0.1,port 8080.....")httpd.serve_forever()
然后用浏览器分别访问http://localhost:8080/ 和http://localhost:8080/?t ,这里先以A页面代表第一个连接,B页面代表第二个连接,如果先访问A页面,则B页面也必须等待A页面完成后(5秒后)才出结果,请求被阻塞了几经努力,在python3的socketserver模块找到了解决办法。其中解决这个问题的一个非常重要的类就是:ThreadingMixIn看这个类的__doc__:
Python代码:
"""Mix-in class to handle each request in a new thread."""太好了,正是我们要找到,参考官方的例子,得到这个Hello World多线程版代码如下:
Python代码:
#!coding=UTF-8from http.server import HTTPServer,BaseHTTPRequestHandlerimport io,shutil,time,socketserverclass MyThreadingHTTPServer(socketserver.ThreadingMixIn, HTTPServer): passclass MyHttpHandler(BaseHTTPRequestHandler): def do_GET(self): print(self.path) if self.path=='/':time.sleep(5) print(self.path) r_str="Hello World"; enc="UTF-8" encoded = ''.join(r_str).encode(enc) f = io.BytesIO() f.write(encoded) f.seek(0) self.send_response(200) self.send_header("Content-type", "text/html; charset=%s" % enc) self.send_header("Content-Length", str(len(encoded))) self.end_headers() shutil.copyfileobj(f,self.wfile)httpd=MyThreadingHTTPServer(('',8080),MyHttpHandler)print("Server started on 127.0.0.1,port 8080.....")httpd.serve_forever()
只需要很少改动,就能将程序变成多线程了,得益于python的多继承机制。官方的文档和例子:
http://docs.python.org/3.0/library/socketserver.html
同时,socketserver里还要一个多进程处理的类:ForkingMixIn,用法和这个一样,只是改下父类名。
在Python3.0中使用HTTPServer处理web请求
继昨天发现wsgi在有点问题而无法使用它来处理web请求后,我在官方文档中看到了一个http.server模块,于是转而研究它而非WSGI。这个模块中有两个重要的类,分别为HTTPServer和BaseHTTPRequestHandler,还有两个示例类,SimpleHTTPRequestHandler,CGIHTTPRequestHandler。还有一个测试方法(test),我参考其中的示例类写了一个HelloWorld程序。上代码:
Python代码
如果将这行代码:
Python代码
Java代码
OK,这个错误到此算是有了一个圆满的结局。
各位对于处理web请求还有什么其他的方法麻烦告诉我。
继昨天发现wsgi在有点问题而无法使用它来处理web请求后,我在官方文档中看到了一个http.server模块,于是转而研究它而非WSGI。这个模块中有两个重要的类,分别为HTTPServer和BaseHTTPRequestHandler,还有两个示例类,SimpleHTTPRequestHandler,CGIHTTPRequestHandler。还有一个测试方法(test),我参考其中的示例类写了一个HelloWorld程序。上代码:
Python代码
from http.server import HTTPServer,BaseHTTPRequestHandler import io,shutil class MyHttpHandler(BaseHTTPRequestHandler): def do_GET(self): r_str="Hello World" enc="UTF-8" encoded = ''.join(r_str).encode(enc) f = io.BytesIO() f.write(encoded) f.seek(0) self.send_response(200) self.send_header("Content-type", "text/html; charset=%s" % enc) self.send_header("Content-Length", str(len(encoded))) self.end_headers() shutil.copyfileobj(f,self.wfile) httpd=HTTPServer(('',8080),MyHttpHandler) print("Server started on 127.0.0.1,port 8080.....") httpd.serve_forever()运行代码,成功,浏览器输出正常。
如果将这行代码:
Python代码
shutil.copyfileobj(f,self.wfile)改为:
Java代码
self.wfile.write(r_str)就会出现昨天的错误。 TypeError: send() argument 1 must be string or buffer, not str
OK,这个错误到此算是有了一个圆满的结局。
各位对于处理web请求还有什么其他的方法麻烦告诉我。
继上次用HTTPServer写了一个简单的HTTPHandler后,我发现如果采用HTTPServer处理WEB请求的话系统没有提供获得请求参数的方法(如Java里的request.getParameter),这哪成,不能获取参数还跟用户交互个屁啊。于是又一头扎进了一望无垠的类库中。下面就是今天早上看来一个多小时的结果。
除上次说用到的那几个之外,这次新加了一个urllib
核心代码:
Python代码
urllib.parse.parse_qs 将字符串解释为dict
这里解释下为什么说是字符串转为dict:从客户端过来的参数,无论是GET还是POST过来的,其值都是一个字符串,"a=1&b=2",
如果是POST那么字符串最后还有一个\n或者\r\n,所以这个方法是GET,POST通用的
那么,先上代码吧:
Python代码
获取参数,最重要的是解码操作,do_GET是最郁闷的,如果客户直接在地址栏输入 xxx/?name=某人 则此时的编码比较麻烦,必须使用name=str(bytes(params["name"][0],'iso-8859-1'),'GBK'),当然了,这是针对我的IE7是这样,其他浏览器我还没进行测试。
这里使用了params["name"][0],parse_sq将每个参数看做是一个数组,就算你只传了一个过来,也会被认为是数组,与java的request.getParametersMap类似。
除上次说用到的那几个之外,这次新加了一个urllib
核心代码:
Python代码
urllib.parse.parse_qs(urllib.parse.unquote(s))urllib.parse.unquote 将被quote的字符串解码,即常规的url编码解码操作
urllib.parse.parse_qs 将字符串解释为dict
这里解释下为什么说是字符串转为dict:从客户端过来的参数,无论是GET还是POST过来的,其值都是一个字符串,"a=1&b=2",
如果是POST那么字符串最后还有一个\n或者\r\n,所以这个方法是GET,POST通用的
那么,先上代码吧:
Python代码
#!coding=UTF-8 from http.server import HTTPServer,BaseHTTPRequestHandler import io,shutil,urllib class MyHttpHandler(BaseHTTPRequestHandler): def do_GET(self): name="World" if '?' in self.path:#如果带有参数 self.queryString=urllib.parse.unquote(self.path.split('?',1)[1]) #name=str(bytes(params['name'][0],'GBK'),'utf-8') params=urllib.parse.parse_qs(self.queryString) print(params) name=params["name"][0] if "name" in params else None r_str="Hello "+name+" <form action='' method='POSt'>Name:<input name='name' /><br /><input type='submit' value='submit' /></form>" enc="UTF-8" encoded = ''.join(r_str).encode(enc) f = io.BytesIO() f.write(encoded) f.seek(0) self.send_response(200) self.send_header("Content-type", "text/html; charset=%s" % enc) self.send_header("Content-Length", str(len(encoded))) self.end_headers() shutil.copyfileobj(f,self.wfile) def do_POST(self): s=str(self.rfile.readline(),'UTF-8')#先解码 print(urllib.parse.parse_qs(urllib.parse.unquote(s)))#解释参数 self.send_response(301)#URL跳转 self.send_header("Location", "/?"+s) self.end_headers() httpd=HTTPServer(('',8080),MyHttpHandler) print("Server started on 127.0.0.1,port 8080.....") httpd.serve_forever()其实这个程序没做什么特殊操作,就是把原来的Hello World改了一下,让客户先输入姓名再显示Hello xxx...
获取参数,最重要的是解码操作,do_GET是最郁闷的,如果客户直接在地址栏输入 xxx/?name=某人 则此时的编码比较麻烦,必须使用name=str(bytes(params["name"][0],'iso-8859-1'),'GBK'),当然了,这是针对我的IE7是这样,其他浏览器我还没进行测试。
这里使用了params["name"][0],parse_sq将每个参数看做是一个数组,就算你只传了一个过来,也会被认为是数组,与java的request.getParametersMap类似。
在Python3.0中处理web请求4-回归WSGI
前面一直使用HTTPServer对web请求进行处理,今天突然想能不能改下,用python3提供的wsgiref进行处理,原来的程序:
Python代码
就改ServerHandler
这个类在wsgiref包里的simple_server.py模块中(Lib/wsgiref/simple_server.py)
原来的ServerHandler是:
Java代码
Java代码
测试 http://localhost:8080,Hello World出来了!
为了方便调试,这里的编码直接写UTF-8了。各位根据自己的需要配置。如果需要使用多线程处理,可以用上一篇文章提到的ThreadingMixIn即可。
前面一直使用HTTPServer对web请求进行处理,今天突然想能不能改下,用python3提供的wsgiref进行处理,原来的程序:
Python代码
from wsgiref.simple_server import make_server def hello_world_app(env,start_response): start_response("200 OK",[("Content-type","text/plain;charset=utf-8")]) return ["Hello World!!"] if __name__ == "__main__": httpd=make_server('',8080,hello_world_app) httpd.handle_request()问题并不在这个程序,异常报的是在write的时候,于是,要改的就是write,改哪里呢?
就改ServerHandler
这个类在wsgiref包里的simple_server.py模块中(Lib/wsgiref/simple_server.py)
原来的ServerHandler是:
Java代码
class ServerHandler(SimpleHandler): server_software = software_version def close(self): try: self.request_handler.log_request( self.status.split(' ',1)[0], self.bytes_sent ) finally: SimpleHandler.close(self)重写_write方法即可:
Java代码
class ServerHandler(SimpleHandler): server_software = software_version def close(self): try: self.request_handler.log_request( self.status.split(' ',1)[0], self.bytes_sent ) self.buf_data.seek(0) shutil.copyfileobj(self.buf_data,self.stdout) finally: SimpleHandler.close(self) def _write(self,data): if not hasattr(self,"buf_data"): self.buf_data=io.BytesIO() if type(data) is str: data=data.encode("UTF-8") self.buf_data.write(data)大功告成。
测试 http://localhost:8080,Hello World出来了!
为了方便调试,这里的编码直接写UTF-8了。各位根据自己的需要配置。如果需要使用多线程处理,可以用上一篇文章提到的ThreadingMixIn即可。
- 在Python3.0中处理web请求3-多线程
- 在Python3.0中使用HTTPServer处理web请求2-获取请求参数
- 在 IIS6.0 中配置 Python3.0 Web 运行环境
- Python3处理HTTP请求
- CXF中Web服务请求处理流程
- 多线程处理socket请求
- 在 Web 请求中使用 XMLHttpRequest
- 在 Web 请求中使用 XMLHttpRequest
- 在struts中处理AJAX请求
- 在struts中处理AJAX请求
- 在 swift中处理网络请求
- 在 swift中处理网络请求
- web请求:servlet处理请求
- 在Web应用程序中执行多线程
- 在Web应用程序中执行多线程
- web 请求的处理
- Web请求处理
- 在多线程中捕获并处理RuntimeException
- icons in win32
- Linux下tcp协议socket的recv函数返回时机分析(粘包)
- Java IO学习笔记:概念与原理
- python 之 string() 模块
- RDLC报表 "错误号"
- 在Python3.0中处理web请求3-多线程
- 欧债危机阴影不散,非美前景不容乐观
- 物理学的困惑: 弦理论崛起了, 科学却衰落了
- 实习以来的小感慨 (欢迎大家积极补充奥!)
- Python使用HTMLParser.HTMLParser处理网页
- JS货币逗号的处理
- QSignalMapper类的用法
- 物理学的困惑: 科学的道德规范和伦理观
- 2012-6-25