2010-10-31 53 views
4

是否可以使用python的标准库xmlrpclib和gevent?目前我试图使用monkey.patch_all(),但没有成功。在pyvent中使用gevent xmlrpclib

from gevent import monkey 
monkey.patch_all() 

import gevent 

import time 

import xmlrpclib 
from SimpleXMLRPCServer import SimpleXMLRPCServer 

import urllib2 

def fetch(url): 
     g = gevent.spawn(urllib2.urlopen, url) 
     return g.get().read() 
def is_even(n): 
    return n%2 == 0 

def req(url): 
     return fetch(url) 

server = SimpleXMLRPCServer(("localhost", 8000)) 
print "Listening on port 8000..." 
server.register_function(is_even, "is_even") 
server.register_function(req, "req") 
server.serve_forever() 

urllib2.urlopen阻止服务器。它看起来对我来说,monkey.patch_all没有修补套接字,这就是为什么它会阻止。

回答

9

套接字已修补好,但您的代码还存在其他问题。

首先,这

def fetch(url): 
    g = gevent.spawn(urllib2.urlopen, url) 
    return g.get().read() 

相同

def fetch(url): 
    return urllib2.urlopen(url).read() 

你在这里产生一个新的greenlet但随后阻塞当前一个,直到新的做。它不会让事情并发。这和运行urlopen并等待它完成一样。

其次,为了利用gevent,需要同时运行多个轻量级线程(greenlet)。

SimpleXMLRPCServer,它然而,被定义为

class SimpleXMLRPCServer(SocketServer.TCPServer, 
         SimpleXMLRPCDispatcher): 

这意味着它用于一次一个连接。

如果您制作属于自己的SimpleXMLRPCServer类,但是使用ThreadingTCPServer而不是TCPServer,那么您应该可以从此处使用gevent中受益。

monkey.patch_all()修补程序threading成为基于greenlet的,所以这样的服务器会为每个新的连接产生一个新的greenlet。

+0

谢谢!螺纹版本按预期工作!但如何从urllib2.urlopen异步返回结果? – frx 2010-11-01 06:20:10

+0

我不确定我是否明白“异步返回结果”的含义。你想达到什么目的? – 2010-11-01 06:22:41

+0

纠正我,如果我即时通讯错误。每个新的连接都在新的greenlet中产生,所以我不需要在新的greenlet中产生urlopen。当urlopen被调用时,如果有多个连接或新事件发生,gevent会切换到其他协程,当内容到达套接字时,它会切换回urlopen协程并返回结果。 – frx 2010-11-01 08:28:19