2012-12-04 11 views
12

Sto usando urllib2 per il caricamento pagina web, il mio codice è:Come impostare il contrassegno TCP_NODELAY durante il caricamento dell'URL con urllib2?

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

Come posso entrare in possesso delle proprietà presa per impostare TCP_NODELAY?

In presa normale, mi sarebbe utilizzando la funzione:

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

Perché lo si imposta quando si chiama un server Web ??? – jgauffin

+0

Sto interrogando un sito web in un momento specifico, quando alcune informazioni dovrebbero essere pubblicate lì. La velocità è molto importante, quindi impostare TCP_NODELAY evita di accumulare piccole porzioni di dati in porzioni più grandi prima di inviare pacchetti. –

+0

* Cosa * 'piccole porzioni di dati'? La richiesta HTTP verrà quasi certamente svuotata dalla libreria in un singolo send() e inviata da TCP come un singolo pacchetto. E l'impostazione di TCP_NODELAY alla fine non cambia il modo in cui il peer invia la risposta. Non è una vera domanda. – EJP

risposta

14

Se avete bisogno di accedere a tali beni a basso livello sul socket utilizzato, si dovrà sovraccaricare alcuni oggetti.

In primo luogo, è necessario creare una sottoclasse di HTTPHandler, che nella libreria standard fare:

class HTTPHandler(AbstractHTTPHandler): 

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

    http_request = AbstractHTTPHandler.do_request_ 

Come si può vedere, si utilizza un HTTPConnection aprire la connessione ... Avrai per sovrascriverlo;) per aggiornare il metodo connect().

Qualcosa del genere dovrebbe essere un buon inizio:

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 è abbastanza intelligente per consentire di sottoclasse qualche gestore e poi usarlo, il urllib2.build_opener è fatto per questo:

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

bella risposta solida! forse sai anche comprimerlo in urllib3 e richieste? –

8

Per le richieste, le classi sembrano essere in request.packages.urllib3; ci sono 2 classi, HTTPConnection e HTTPSConnection. Essi dovrebbero essere monkeypatchable in atto al livello superiore del modulo:

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

fantastico. Ho già visto questa patch per le scimmie per la verifica dei certificati server e sni. Spero che non entrino in conflitto. –

+0

Al momento sto scrivendo questo, urllib3 (e quindi richieste) predefinito su TCP_NODELAY. Dai un'occhiata a 'requests.packages.urllib3.connection.HTTPConnection', in particolare' default_socket_options'. –

1

Avete usare urllib2?

In alternativa, è possibile utilizzare httplib2, che ha l'opzione TCP_NODELAY impostata.

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

Si aggiunge una dipendenza al progetto, ma sembra meno fragile rispetto scimmia patch.