Использование gevent с python xmlrpclib


Можно ли использовать стандартные библиотеки python xmlrpclib с gevent? В настоящее время я пытаюсь использовать обезьяну.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 блокирует сервер. Мне кажется, что это обезьяна.patch_all не залатал сокет, вот почему он блокируется.

1 4

1 ответ:

Сокет исправлен нормально, но есть и другие проблемы с вашим кодом.

Во-первых, это

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

То же самое, что

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

Вы создаете здесь Новый Зеленый лист, но затем блокируете текущий, пока этот новый не будет завершен. Это не делает вещи параллельными. Это в точности то же самое, что просто запустить urlopen и ждать его завершения.

Во-вторых, чтобы воспользоваться преимуществом gevent , должно быть более одной легкой нити (greenlet) бежать одновременно.

SimpleXMLRPCServer, однако, определяется как

class SimpleXMLRPCServer(SocketServer.TCPServer,
                         SimpleXMLRPCDispatcher):
Это означает, что он обслуживает одно соединение за раз.

Если вы создадите свой собственный класс SimpleXMLRPCServer, но используете ThreadingTCPServer вместо TCPServer, Вы сможете извлечь выгоду из использования gevent здесь.

monkey.patch_all() патчи threading, чтобы стать greenlet-based, так что такой сервер будет порождать новый greenlet для каждого нового соединения.