http-Anforderung mit timeout, maximale Größe und connection pooling
Ich bin auf der Suche nach einer Möglichkeit in Python (2.7), um HTTP-Anforderungen 3 Anforderungen:
- timeout (für Zuverlässigkeit)
- Inhalte maximale Größe (für die Sicherheit)
- Verbindungs-pooling (für die Leistung)
Ich habe ziemlich jedes python-HTTP-Bibliothek, aber keiner von Ihnen erfüllen meine Anforderungen. Zum Beispiel:
urllib2: gut, aber kein pooling
import urllib2
import json
r = urllib2.urlopen('https://github.com/timeline.json', timeout=5)
content = r.read(100+1)
if len(content) > 100:
print 'too large'
r.close()
else:
print json.loads(content)
r = urllib2.urlopen('https://github.com/timeline.json', timeout=5)
content = r.read(100000+1)
if len(content) > 100000:
print 'too large'
r.close()
else:
print json.loads(content)
Anforderungen: keine max Größe
import requests
r = requests.get('https://github.com/timeline.json', timeout=5, stream=True)
r.headers['content-length'] # does not exists for this request, and not safe
content = r.raw.read(100000+1)
print content # ARF this is gzipped, so not the real size
print json.loads(content) # content is gzipped so pretty useless
print r.json() # Does not work anymore since raw.read was used
urllib3: nie bekam Sie die "read" - Methode zu arbeiten, auch mit einer 50MB-Datei ...
httplib: httplib.HTTPConnection ist kein pool (nur eine Verbindung)
Kann ich kaum glauben, dass die urllib2 ist der beste HTTP-Bibliothek, die ich nutzen kann ! Also, wenn jemand weiß, was librairy können dies tun, oder wie eine der früheren librairy ...
EDIT:
Die beste Lösung, die ich gefunden Dank Martijn Pieters (StringIO nicht langsam nach unten, auch für große Dateien, wo str Ergänzung nicht viele).
r = requests.get('https://github.com/timeline.json', stream=True)
size = 0
ctt = StringIO()
for chunk in r.iter_content(2048):
size += len(chunk)
ctt.write(chunk)
if size > maxsize:
r.close()
raise ValueError('Response too large')
content = ctt.getvalue()
- Am
ctt.write(chunk)
Zeile bekomme ich einenTypeError: string argument expected, got 'bytes'
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie es mit
requests
genau richtig; aber Sie müssen wissen, dass dieraw
Objekt ist Teil derurllib3
Mut und nutzen die zusätzlichen Argumente derHTTPResponse.read()
- Aufruf unterstützt, können Sie angeben, die Sie Lesen möchten decodiert Daten:Alternativ können Sie die
decode_content
- Flagge auf derraw
Objekt vor dem Lesen:Wenn Sie nicht mögen, erreichen in
urllib3
Mut wie Sie, dass, nutzen Sie dieAntwort.iter_content()
Durchlaufen die decodierten Inhalte in Blöcken; es verwendet die zugrunde liegendeHTTPResponse
zu (mit der.stream()
generator-version:Es ist der feine Unterschied hier, wie die komprimierten Daten Größen werden hier behandelt;
r.raw.read(100000+1)
immer nur gelesen 100k bytes der komprimierten Daten; die unkomprimierten Daten getestet wird gegen Sie Ihre maximale Größe. Dieiter_content()
Methode Lesen Sie mehr unkomprimierte Daten in dem seltenen Falle, dass die komprimierten stream ist größeren als die unkomprimierten Daten.Weder Methode ermöglicht
r.json()
zu arbeiten; dieresponse._content
- Attribut nicht gesetzt ist, durch diesen; Sie können dies manuell tun natürlich. Aber da die.raw.read()
und.iter_content()
fordert schon erhalten Sie Zugriff auf den Inhalt in Frage, es gibt wirklich keine Notwendigkeit.urllib2
akzeptiert keine Kompressionr.raw.read
vergleichen Sie die Gzip-Größe und -r.iter_content
vergleichen Sie die wirkliche Größe aber wirklich langsam nach unten der code (vielleicht ein stream würde es schneller).r.iter_content()
verlangsamt den code hängt ganz von der Größe des chunks Lesen; eine kleine chunk-Größe erfordert mehr schleifendurchläufe. Und es arbeitet auf einer stream bereits.content += chunk
es langsam nach unten durch python-str non Veränderbarkeit. StringIO.StringIO gelöst.''.join()
am Ende, aberStringIO()
kapselt das schön.timeout
aber es gilt nur für den Verbindungsversuch.content = b''
+1decode_content=True
oben ist der code anfällig. Unrelated: Sie können, wenn Sie möchten, um Lesen Sie komprimierte Daten miturllib2
wenn Sie es Lesen in den Speicher, wie in deinem Fall. Python-3-code ermöglicht das streamen gzipped-Inhalt.pycurl
(das hat horrende API). Die alternative ist, um die Verbindung zu schließen, verwendenTimer()
z.B., wennr
isturllib.request.urlopen()
Reaktion dannTimer(timeout, r.fp.raw._sock.shutdown, [socket.SHUT_RDWR])
durchsetzen kann die total read timeout (wenn verschiedene.close()
Methoden wurden idempotent hier, dann würde es weniger hässlich zu erreichen, ohne in die Eingeweide Weg zur Umsetzung des timeout).response.content
oderresponse.text
Eigenschaften (laden der gesamte Inhalt wird als Binär-oder Unicode-string). Alle Dekompression erfolgt in urllib3 in beiden Fällen keinen Schutz gegen eine Dekompression Bombe ist darin enthalten.content = b''
noch Essen, bis die Speicher. DieStringIO
option ist eine interessante alternative, erfordert aber ein zusätzliches Modul importieren. Wahrscheinlich einfacher, um die chunk-Länge? Sosize = 0
stattcontent = b''
, und dannsize += len(chunk)
stattcontent += chunk
und überprüfen Sie dannif size > maxsize
. Könnte auch überprüfen Sie zunächstif int(r.headers.get('Content-Length')) > maxsize
, in welchem Fall Sie nicht haben, um download Brocken, wenn "Content-Length" ist tatsächlich eingestellt.