2012-12-04 20 views
12

używam urllib2 do ładowania strony internetowej, mój kod jest:Jak ustawić flagę TCP_NODELAY podczas ładowania adresu URL za pomocą urllib2?

httpRequest = urllib2.Request("http:/www....com") 
pageContent = urllib2.urlopen(httpRequest) 
pageContent.readline() 

Jak mogę zdobyć właściwości gniazd ustawić TCP_NODELAY?

W normalnym gniazda byłbym za pomocą funkcji:

socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) 
+1

Dlaczego ustawiasz to podczas połączenia z serwerem internetowym ??? – jgauffin

+0

Przepytałem stronę internetową w określonym czasie, gdy niektóre informacje powinny zostać tam opublikowane. Szybkość jest bardzo ważna, dlatego ustawienie TCP_NODELAY zapobiega gromadzeniu się małych porcji danych na większe porcje przed wysłaniem pakietu. –

+0

* Jakie * "małe porcje danych"? Żądanie HTTP prawie na pewno zostanie przepelnione przez bibliotekę w jednym wysłaniu() i wysłane przez TCP jako pojedynczy pakiet. Ustawienie wartości TCP_NODELAY na końcu nie zmienia sposobu wysyłania odpowiedzi przez węzeł sieci. To nie jest prawdziwe pytanie. – EJP

Odpowiedz

14

Jeżeli chcesz mieć dostęp do takiej własności niski poziom na gnieździe używane, musisz przeciążać niektóre obiekty.

Po pierwsze, trzeba utworzyć podklasę HTTPHandler, że w standardowej bibliotece zrobić:

class HTTPHandler(AbstractHTTPHandler): 

    def http_open(self, req): 
     return self.do_open(httplib.HTTPConnection, req) 

    http_request = AbstractHTTPHandler.do_request_ 

Jak widać, używa HTTPConnection otworzyć połączenie ... Musisz nadpisać to również;), aby zaktualizować metodę connect().

Coś jak to powinno być dobry początek:

class LowLevelHTTPConnection(httplib.HTTPConnection): 

    def connect(self): 
     httplib.HTTPConnection.connect(self) 
     self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) 


class LowLevelHTTPHandler(HTTPHandler): 

    def http_open(self, req): 
     return self.do_open(LowLevelHTTPConnection, req) 

urllib2 jest wystarczająco inteligentny, aby umożliwić podklasy trochę obsługi, a następnie użyć, tym urllib2.build_opener jest za to:

urllib2.install_opener(urllib2.build_opener(LowLevelHTTPHandler)) # tell urllib2 to use your HTTPHandler in replacement of the standard HTTPHandler 
httpRequest = urllib2.Request("http:/www....com") 
pageContent = urllib2.urlopen(httpRequest) 
pageContent.readline() 
+1

fajna solidna odpowiedź! czy może wiesz również, aby wycisnąć go do urllib3 i żądań? –

8

W przypadku żądań klasy wyglądają na: request.packages.urllib3; istnieją 2 klasy, HTTPConnection i HTTPSConnection. Powinny być monkeypatchable w miejscu na najwyższym poziomie modułu:

from requests.packages.urllib3 import connectionpool 

_HTTPConnection = connectionpool.HTTPConnection 
_HTTPSConnection = connectionpool.HTTPSConnection 

class HTTPConnection(_HTTPConnection): 
    def connect(self): 
     _HTTPConnection.connect(self) 
     self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) 

class HTTPSConnection(_HTTPSConnection): 
    def connect(self): 
     _HTTPSConnection.connect(self) 
     self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) 

connectionpool.HTTPConnection = HTTPConnection 
connectionpool.HTTPSConnection = HTTPSConnection 
+0

niesamowite. Widziałem już to łatanie małp dla weryfikacji certyfikatu serwera i sni. Mam nadzieję, że nie kłócą się. –

+0

W chwili pisania tego, urllib3 (a więc żądania) domyślnie TCP_NODELAY. Spójrz na 'requests.packages.urllib3.connection.HTTPConnection', w szczególności' default_socket_options'. –

1

Czy musisz użyć urllib2?

Alternatywnie możesz użyć httplib2, który ma ustawioną opcję TCP_NODELAY.

https://code.google.com/p/httplib2/

Dodaje zależność do swojego projektu, ale wydaje się mniej kruche niż małpy łatania.