2009-09-02 17 views
7

Chciałbym przeczytać stronę asynchronicznie, co nie jest możliwe z urllib, o ile wiem. Teraz próbowałem czytać przy użyciu zwykłych gniazd, ale HTTP daje mi piekło. Wpadam na wszelkiego rodzaju funky kodowania, na przykład transfer-encoding: chunked, muszę przetworzyć wszystkie te rzeczy ręcznie i mam ochotę na kodowanie C, nie pytona w tej chwili.Czytanie strony z asyncore

Czy nie jest ładniejszy sposób, jak URLLib, asynchronicznie? Naprawdę nie mam ochoty na ponowne implementowanie całej specyfikacji HTTP, kiedy to wszystko zostało zrobione wcześniej.

Twisted nie jest obecnie opcją.

Pozdrowienia,

Tom

Odpowiedz

5

Pan spojrzał na http://asynchttp.sourceforge.net/?

„Asynchronous klient HTTP dla Pythona

do«asynchttp»” moduł jest logicznym rozszerzeniem biblioteki Pythona asynchat "moduł, który jest zbudowany na«asyncore»i«Select»moduły. Naszym celem jest zapewnia funkcjonalność doskonałego modułu "httplib" bez używania blokujących gniazd. "

Ostatnie zatwierdzenie projektu miało miejsce 2001-05-29, więc wygląda na martwe. Ale i tak może to być interesujące.

Nota prawna: Nie użyłem tego sam.

Ponadto, this blog post ma pewne informacje na temat asynchronicznego HTTP.

7

można zaimplementować asynchroniczne nazywają siebie. W przypadku każdego połączenia uruchom nowy wątek (lub spróbuj go pobrać z puli) i użyj wywołania zwrotnego, aby go przetworzyć.

Można to zrobić bardzo ładnie z dekoratora:

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

Niestety, jak już mówiłem, chcę asynchronicznych gniazd, nie wątkach. – Tom

+1

Czy jestem jedyną osobą, która myśli, że to rozwiązanie jest * genialne *?Rzeczą, która sprawia, że ​​lepsze niż * wszystkie inne * asynchroniczne metody HTTP są: tak naprawdę jest to w pełni ogólne asynchroniczne rozwiązanie * cokolwiek *. Możesz zamienić 'get_webpage' na dowolny kod, który chcesz, i to się stanie asynchronicznie. – robru

1

Najdalej przybyłem, używając zmodyfikowanego asynchttp, które sugerował codeape. Próbowałem użyć zarówno asyncore/asynchat i asynchttp, z dużą ilością bólu. Zajęło mi to zbyt dużo czasu, aby naprawić wszystkie błędy w nim zawarte (istnieje metoda handle_read, prawie skopiowana z asyncore, tylko źle wcięta i dawała mi bóle głowy z fragmentarycznym kodowaniem). Asyncore i asynchat najlepiej nie używać zgodnie z pewnymi wskazówkami, które dostałem w google.

Osiedliłem się z pokręconym, ale to oczywiście nie wchodzi w grę.

Może również zależeć od tego, co próbujesz zrobić ze swoją aplikacją i dlaczego chcesz otrzymać asynchroniczne żądania, czy wątki są opcją, czy nie, jeśli programujesz GUI lub coś innego, więc jeśli możesz rzucić trochę więcej informacji , to zawsze dobre. Jeśli nie, zagłosuję na sugerowaną powyżej wersję gwintowaną, która zapewnia znacznie większą czytelność i łatwość konserwacji.

1

Asyncore prosty przykład klient HTTP jest bardzo proste :)

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()