twisted 2

最近忙,发点旧文凑数-_-|||,这是三月份试用Twisted时记的一点笔记)

Twisted是一个功能极为强大的异步网络应用开发库——当然是Python的。印象中大概也就只有ACE有这么强悍,但Twisted在易用性方面要好很多——这其中当然少不了Python的功劳(ACE是用C++的)。

但Python也有其缺点,其中之一就是因为GIL的存在使得用Python写多线程应用的意义不大,那么对于像Twisted这样基于Reactor模式实现的单一Event Loop的应用开发环境来说,就有一点局限:整个应用(或者说整个进程)都必须围绕着reactor来。这样的话做一些纯后端的应用是没什么问题,比如像网页爬虫(Scrapy就是基于Twsited的)一类的应用。但这显然不够,很多应用还是需要有前端界面的——比如像BT、电驴这样的下载工具。MLDonkey采用的方法就是提供一个WEB的管理界面来与用户交互——当然,MLDonkey并不是用Python开发的。

这是一个很好的思路。所以Twisted提供了一套WEB开发环境以实现这样的目的。

关于twisted.web部分的开发,官方的文档 显得太过于简单了,特别是连基本的request对象的参考文档都没有。还好gashero整理了一部分在《Twisted的WEB开发 》,引用一下(有补充):

channel :包含上级的HTTP协议对象。
transport :通信对象。
method :HTTP方法,如GET和POST。
uri :全部请求的URI。
path :具体的请求路径,不含参数。
args :请求参数,包括URL参数和POST参数。格式如 {’key’:[’val1′,’val2′],} 。
received_headers :请求报文的头字段。
received_cookies :请求报文的cookie。
content :请求报文的实体主体,文件对象。
clientproto :发出请求的客户端的HTTP版本。
client :请求的客户端地址对象,包括type、host和port属性,分别记录协议(这里固定为TCP)、IP和端口号
host :本机接收请求的地址对象
getHeader(key) :获取请求的头字段。
getCookie(key) :获取请求的cookie。
getAllHeaders() :所有请求的头字段字典,就是返回received_headers。
getRequestHostname() :请求的host字段,不含端口号。
getHost() :原始请求的通信地址,返回host。
getClientIP() :获取客户端IP。
getUser() :获取basic验证中的用户名。
getPassword() :获取basic验证中的密码。
getClient() :获取客户端地址对象

一个最基本的Web应用如下:

[python]  view plain copy
  1. from twisted.web import server, resource  
  2. from twisted.internet import reactor  
  3. class Simple(resource.Resource):  
  4.     isLeaf=True  
  5.     def render_GET(self, request):  
  6.         return "Hello, world!"  
  7. reactor.listenTCP(8080, server.Site(Simple()))  
  8. reactor.run()  

然后运行起来就可以通过URL:http://localhost:8080 访问这个程序的页面了。

注意其中的的isLeaf是必须的。不过也还有另一种方法可以实现同样的功能:

[python]  view plain copy
  1. from twisted.web import server, resource  
  2. from twisted.internet import reactor  
  3. class Simple(resource.Resource):  
  4.     def __init__(self):  
  5.         resource.Resource.__init__(self)  
  6.         self.putChild("", self)  
  7.     def render_GET(self, request):  
  8.         return "Hello, world!"  
  9. reactor.listenTCP(8080, server.Site(Simple()))  
  10. reactor.run()  

这个方法好理解,就是把这个对象挂到请求链接的根目录上。以此类推就可以实现带子目录请求的页面:

[python]  view plain copy
  1. from twisted.web import server, resource  
  2. from twisted.internet import reactor  
  3. class ChildSimple(resource.Resource):  
  4.     isLeaf=True  
  5.     def render_GET(self, request):  
  6.         return "Hello, child!"  
  7. class Simple(resource.Resource):  
  8.     def __init__(self):  
  9.         resource.Resource.__init__(self)  
  10.         self.putChild("", self)  
  11.         self.putChild("child", ChildSimple())  
  12.     def render_GET(self, request):  
  13.         return "Hello, world!"  
  14. reactor.listenTCP(8080, server.Site(Simple()))  
  15. reactor.run()  

现在可以通过URL:http://localhost:8080/child 访问这个子页面了。不过生成子页面还有一个动态的办法:

[python]  view plain copy
  1. from twisted.web import server, resource  
  2. from twisted.internet import reactor  
  3. class ChildSimple(resource.Resource):  
  4.     isLeaf=True  
  5.     def __init__(self, id):  
  6.         resource.Resource.__init__(self)  
  7.         self.id=id  
  8.     def render_GET(self, request):  
  9.         return "Hello, No. %s visitor!" % self.id  
  10. class Simple(resource.Resource):  
  11.     def __init__(self):  
  12.         resource.Resource.__init__(self)  
  13.         self.putChild("", self)  
  14.     def render_GET(self, request):  
  15.         return "Hello, world!"  
  16.     def getChild(self, path, request):  
  17.         return ChildSimple(path)  
  18. reactor.listenTCP(8080, server.Site(Simple()))  
  19. reactor.run()  

现在可以试试URL:http://localhost:8080/1234 访问了。其中1234可以换成任何数字(实际上上面的程序对此未作限制,即使输入任何字符也是可以的)。

接下来是静态内容的使用:

[python]  view plain copy
  1. from twisted.web import server, resource, static  
  2. from twisted.internet import reactor  
  3. class Simple(resource.Resource):  
  4.     def __init__(self):  
  5.         resource.Resource.__init__(self)  
  6.         self.putChild("", self)  
  7.         self.putChild("static", static.File("/var/www/htdocs"))  
  8.     def render_GET(self, request):  
  9.         return "Hello, world!"  
  10. reactor.listenTCP(8080, server.Site(Simple()))  
  11. reactor.run()  

访问一下URL:http://localhost:8080/static 试试就知道了。

这些对于Web开发都是些基本的功能,稍微复杂一点的网页要做起来还是很痛苦的。但是Python是很灵活的东西,资源也很丰富,所以实际上问题也不大。比如在getChild方法里加上routing的实现,再加一个mako一类的模板,功能立即强大很多(貌似搞得像Pylons了)——只是数据库操作还是需要谨慎一些,简单地加上SQLAlchemy之类的ORM也不是不行,但是它对数据库的访问是阻塞式的,可能导致Twisted应用的性能下降很大。

所幸的是一般来说为Twisted应用增加Web交互界面很少还有需要操作数据库的,即使必须要有,Twisted也提供了异步的数据库访问接口——虽然功能不可能像SQLAlchemy那么强大,对于简单的应用应该也足够了。

虽然WEB界面已经很方便了,但也许还会有人想要用交互式GUI,这也没问题。Twisted的Web库提供了对XMLRPC和SOAP的支持。以简单一些的XMLRPC为例:

[python]  view plain copy
  1. from twisted.web import server, resource, xmlrpc  
  2. from twisted.internet import reactor  
  3. class XREcho(xmlrpc.XMLRPC):  
  4.     def xmlrpc_echo(self, bar):  
  5.         return bar  
  6. reactor.listenTCP(8080, server.Site(XREcho()))  
  7. reactor.run()  

客户端的调用方式是:

[python]  view plain copy
  1. import xmlrpclib  
  2. s = xmlrpclib.Server("http://localhost:8080/")  
  3. s.echo("Hello!")  

上面的代码执行后将回显。

实际上XMLRPC对象也是一种Resource,所以也可以简单地用putChild放到子目录下去。或者如果需要对xmlrpc的request进行控制——比如增加authentication或者其它的客户端调用限制,可以在_cbRender方法里实现,具体可参考web.xmlrpc的源码。

关于用Twisted进行Web开发的更多内容请参考官方文档和源码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值