2009-09-02 17 views
7

Me gustaría leer un sitio web de forma asíncrona, lo que no es posible con urllib hasta donde yo sé. Ahora traté de leer con sockets simples, pero HTTP me está dando el infierno. Me encuentro con todo tipo de codificaciones funky, por ejemplo, codificación de transferencia: fragmentada, tengo que analizar todo eso manualmente, y me siento como si codificara C, no python en este momento.Leyendo un sitio web con asyncore

¿No hay una manera más agradable como URLLib, asincrónicamente? Realmente no tengo ganas de volver a implementar la especificación HTTP completa, cuando todo se ha hecho antes.

Twisted no es una opción actualmente.

Saludos,

Tom

Respuesta

5

¿Has mirado en http://asynchttp.sourceforge.net/?

"Cliente HTTP asincrónico para Python

El 'AsyncHTTP'' módulo es una extensión lógica de la biblioteca de Python 'asynchat' módulo que se basa en el 'asyncore' y 'seleccione' módulos. Nuestro objetivo es proporcione la funcionalidad del excelente módulo 'httplib' sin usar sockets de bloqueo. "

El último compromiso del proyecto fue 2001-05-29, por lo que parece muerto. Pero podría ser de interés de todos modos.

Descargo de responsabilidad: Yo no lo he usado.

Además, this blog post tiene alguna información sobre async HTTP.

7

Se puede implementar un asincrónica llama a sí mismo. Para cada llamada, inicie un nuevo hilo (o intente obtener uno de un grupo) y use una devolución de llamada para procesarlo.

Esto se puede hacer muy bien con un decorador:

def threaded(callback=lambda *args, **kwargs: None, daemonic=False): 
    """Decorate a function to run in its own thread and report the result 
    by calling callback with it.""" 
    def innerDecorator(func): 
     def inner(*args, **kwargs): 
      target = lambda: callback(func(*args, **kwargs)) 
      t = threading.Thread(target=target) 
      t.setDaemon(daemonic) 
      t.start() 
     return inner 
    return innerDecorator 

@threaded() 
def get_webpage(url): 
    data = urllib.urlopen(url).read() 
    print data 
+2

Lo sentimos, como ya he dicho, quiero sockets asíncronas, no roscados. – Tom

+1

¿Soy la única persona que piensa que esta solución es * brillante *?Lo que hace mejor que * todos los demás * los métodos HTTP asíncronos es que en realidad es una solución asíncrona completamente general para * cualquier cosa *. Puede reemplazar 'get_webpage' con cualquier código que desee y que ocurra de forma asíncrona. – robru

1

Lo más lejos que llegué fue usando asynchttp modificado, sugirió ese codeape. He intentado usar tanto asyncore/asynchat como asynchttp, con mucho dolor. Me tomó demasiado tiempo tratar de arreglar todos los errores (hay un método handle_read, casi copiado de asyncore, solo con sangría grave y me estaba dando dolores de cabeza con codificación fragmentada). Además, asyncore y asynchat no se usan de acuerdo con algunos consejos que obtuve en google.

Me he conformado con retorcido, pero eso es obviamente fuera de cuestión para usted.

También podría depender de qué intentas hacer con tu aplicación y por qué quieres las solicitudes asincrónicas, si los subprocesos son una opción o no, si estás haciendo una programación GUI o algo más, así que si pudieras descartar algo más de información eso siempre es bueno Si no, votaría por la versión con hebras sugerida anteriormente, ofrece mucha más legibilidad y facilidad de mantenimiento.

1

asyncore ejemplo sencillo cliente HTTP es bastante sencillo :)

http://docs.python.org/library/asyncore.html

import asyncore, socket 

class HTTPClient(asyncore.dispatcher): 

    def __init__(self, host, path): 
     asyncore.dispatcher.__init__(self) 
     self.create_socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.connect((host, 80)) 
     self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % path 

    def handle_connect(self): 
     pass 

    def handle_close(self): 
     self.close() 

    def handle_read(self): 
     print self.recv(8192) 

    def writable(self): 
     return (len(self.buffer) > 0) 

    def handle_write(self): 
     sent = self.send(self.buffer) 
     self.buffer = self.buffer[sent:] 


client = HTTPClient('www.python.org', '/') 
asyncore.loop() 
Cuestiones relacionadas