2010-10-31 64 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