在Python中使用gevent和xmlrpclib

4 投票
1 回答
2173 浏览
提问于 2025-04-16 06:21

可以用Python的标准库xmlrpclib配合gevent吗?我现在尝试使用monkey.patch_all(),但没有成功。

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没有对socket进行补丁,所以它会阻塞。

1 个回答

9

这个socket修补得不错,但你的代码还有其他问题。

首先,这段代码

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。

撰写回答