2012-12-04 14 views
12

Ich verwende urllib2 zum Laden von Web-Seite, ist mein Code:Wie setze ich das TCP_NODELAY Flag beim Laden der URL mit urllib2?

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

Wie kann ich halten, den Sockel Eigenschaften erhalten TCP_NODELAY zu setzen?

Im normalen Steckdose würde ich Funktion werden:

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

Warum legen Sie es beim Aufruf eines Webservers fest ??? – jgauffin

+0

Ich besuche eine Website zu einem bestimmten Zeitpunkt, wenn einige Informationen dort veröffentlicht werden sollen. Die Geschwindigkeit ist sehr wichtig, so dass das Setzen von TCP_NODELAY verhindert, dass kleine Teile von Daten in größeren Portionen gesammelt werden, bevor Pakete gesendet werden. –

+0

* Was * 'kleine Teile von Daten'? Die HTTP-Anforderung wird fast sicher von der Bibliothek in einem einzigen send() gelöscht und von TCP als einzelnes Paket gesendet. Und das Festlegen von TCP_NODELAY an Ihrem Ende ändert nicht, wie der Peer die Antwort sendet. Keine echte Frage. – EJP

Antwort

14

Wenn Sie auf den Sockel eingesetzt, um solche niedrigen Niveau Eigenschaft zugreifen müssen, werden Sie einige Objekte überlasten müssen.

Zuerst werden Sie eine Unterklasse von HTTPHandler erstellen müssen, dass in der Standardbibliothek tun:

class HTTPHandler(AbstractHTTPHandler): 

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

    http_request = AbstractHTTPHandler.do_request_ 

Wie Sie sehen können, ist es ein HTTPConnection verwendete Verbindung zu öffnen ... Sie müssen um es auch zu überschreiben;) um die connect() Methode zu aktualisieren.

So etwas sollte ein guter Anfang sein:

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 intelligent genug, um Ihnen zu erlauben, einige Handler zu Unterklasse und dann verwenden, wird die urllib2.build_opener dafür gemacht:

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

nette solide Antwort! Weißt du vielleicht auch, es in urllib3 und Anfragen zu pressen? –

8

Für Anfragen scheinen die Klassen in request.packages.urllib3 zu sein; Es gibt 2 Klassen, HTTPConnection und HTTPSConnection. Sie sollten auf Modul obersten Ebene statt monkeypatchable sein:

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

genial. Ich habe dieses Affe-Patchen bereits für Server-Zertifikat-Verifizierung und Sni gesehen. Ich hoffe, dass sie nicht in Konflikt geraten. –

+0

Von dem Zeitpunkt an, an dem ich dies schreibe, ist urllib3 (und damit Anfragen) standardmäßig auf TCP_NODELAY eingestellt. Sehen Sie sich 'requests.packages.urllib3.connection.HTTPConnection' an, speziell' default_socket_options'. –

1

Haben Sie verwenden urllib2?

Alternativ können Sie httplib2 verwenden, für das die Option TCP_NODELAY festgelegt ist.

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

Es fügt eine Abhängigkeit zu einem Projekt, scheint aber weniger spröde als Affe Patchen.