asyncore - Asynchroner IO/Handler

Link zu Doug Hellmanns Original Artikel

Zweck: Asynchrones IO Handling
Python: ab 1.5.2

Das asyncore Modul beinhaltet Tools um mit IO-Objekten wie mit Sockets zu arbeiten, so dass diese asynchron verwaltet werden können (anstelle von threading zum Beispiel). Die Hauptklasse, die zur Verfügung gestellt wird ist der dispatcher, ein Wrapper um einen Socket der beim Aufruf der Hauptschleife loop() mit Hooks zur Ereignissen wie verbinden, lesen und schreiben verwaltet.

Clients

Erstelle eine Subklasse von dispatcher um einen auf asynchore basierenden Client zu erstellen und Implementierungen zum Erstellen, Lesen und Schreiben von Sockets zur Verfügung zu stellen. Laßt uns diesen, auf der Dokumentation der Standarbibliothek basierenden HTTP Client, untersuchen.

import asyncore
import logging
import socket
from cStringIO import StringIO
import urlparse

class HttpClient(asyncore.dispatcher):

    def __init__(self, url):
        self.url = url
        self.logger = logging.getLogger(self.url)
        self.parsed_url = urlparse.urlparse(url)
        asyncore.dispatcher.__init__(self)
        self.write_buffer = 'GET %s HTTP/1.0\r\n\r\n' % self.url
        self.read_buffer = StringIO()
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        address = (self.parsed_url.netloc, 80)
        self.logger.debug('Verbinde mit %s', address)
        self.connect(address)

    def handle_connect(self):
        self.logger.debug('handle_connect()')

    def handle_close(self):
        self.logger.debug('handle_close()')
        self.close()

    def writable(self):
        is_writable = (len(self.write_buffer) > 0)
        if is_writable:
            self.logger.debug('writable() -> %s', is_writable)
        return is_writable
    
    def readable(self):
        self.logger.debug('readable() -> True')
        return True

    def handle_write(self):
        sent = self.send(self.write_buffer)
        self.logger.debug('handle_write() -> "%s"', self.write_buffer[:sent])
        self.write_buffer = self.write_buffer[sent:]

    def handle_read(self):
        data = self.recv(8192)
        self.logger.debug('handle_read() -> %d bytes', len(data))
        self.read_buffer.write(data)

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG,
                        format='%(name)s: %(message)s',
                        )

    clients = [
        HttpClient('http://www.python.org/'),
        HttpClient('http://www.doughellmann.com/PyMOTW/contents.html'),
        ]

    logging.debug('STARTE SCHLEIFE')

    asyncore.loop()

    logging.debug('BEENDE SCHLEIFE')

    for c in clients:
        response_body = c.read_buffer.getvalue()
        print c.url, 'got', len(response_body), 'bytes'    

Als erstes wird der Socket in __init__() mit der Methode create_socket() aus der Basisklasse erstellt.

In der Übersetzung