Requests ist eine wirklich schöne Bibliothek. Ich möchte es zum Herunterladen großer Dateien (> 1 GB) verwenden. Das Problem ist, dass es nicht möglich ist, die gesamte Datei im Speicher zu halten. Ich muss sie in Blöcken lesen. Und dies ist ein Problem mit dem folgenden Code
import requests
def DownloadFile(url)
local_filename = url.split('/')[-1]
r = requests.get(url)
f = open(local_filename, 'wb')
for chunk in r.iter_content(chunk_size=512 * 1024):
if chunk: # filter out keep-alive new chunks
f.write(chunk)
f.close()
return
Aus irgendeinem Grund funktioniert es nicht so. Die Antwort wird weiterhin in den Speicher geladen, bevor sie in einer Datei gespeichert wird.
AKTUALISIEREN
Wenn Sie einen kleinen Client (Python 2.x / 3.x) benötigen, der große Dateien von FTP herunterladen kann, finden Sie ihn hier . Es unterstützt Multithreading und erneutes Verbinden (es überwacht Verbindungen) und optimiert Socket-Parameter für die Download-Aufgabe.
quelle
chunk_size
ist entscheidend. Standardmäßig ist es 1 (1 Byte). Das bedeutet, dass für 1 MB 1 Million Iterationen durchgeführt werden. docs.python-requests.org/en/latest/api/…f.flush()
scheint unnötig. Was versuchst du damit zu erreichen? (Ihre Speichernutzung beträgt nicht 1,5 GB, wenn Sie sie löschen).f.write(b'')
(wenniter_content()
möglicherweise eine leere Zeichenfolge zurückgegeben wird) sollte harmlos sein undif chunk
könnte daher auch gelöscht werden.f.flush()
keine Daten auf die physische Festplatte. Es überträgt die Daten an das Betriebssystem. Normalerweise reicht es aus, wenn kein Stromausfall vorliegt.f.flush()
macht den Code hier ohne Grund langsamer. Das Leeren erfolgt, wenn der entsprechende Dateipuffer (innerhalb der App) voll ist. Wenn Sie häufiger schreiben müssen; Übergeben Sie den Parameter buf.size anopen()
.r.close()
Es ist viel einfacher, wenn Sie
Response.raw
undshutil.copyfileobj()
:Dadurch wird die Datei ohne übermäßigen Speicherplatz auf die Festplatte gestreamt, und der Code ist einfach.
quelle
with
Block verwenden, um die Anfrage zu stellen:with requests.get(url, stream=True) as r:
with requests.get()
erst am 07.06.2017 zusammengeführt wurde! Ihr Vorschlag ist für Personen mit Anfragen 2.18.0 oder höher angemessen. Ref: github.com/requests/requests/issues/4136read
Methode ersetzen :response.raw.read = functools.partial(response.raw.read, decode_content=True)
Nicht genau das, was OP gefragt hat, aber ... es ist lächerlich einfach, das zu tun mit
urllib
:Oder auf diese Weise, wenn Sie es in einer temporären Datei speichern möchten:
Ich habe den Prozess beobachtet:
Und ich sah die Datei wachsen, aber die Speichernutzung blieb bei 17 MB. Vermisse ich etwas
quelle
from urllib import urlretrieve
shutil.copyfileobj
mit den meisten Stimmen, siehe meine und andere Kommentare dortIhre Chunk-Größe könnte zu groß sein. Haben Sie versucht, das zu löschen - vielleicht 1024 Bytes gleichzeitig? (Sie können
with
auch die Syntax aufräumen)Wie können Sie übrigens feststellen, dass die Antwort in den Speicher geladen wurde?
Es hört sich so an, als würde Python die Daten nicht von anderen in eine Datei leeren SO Fragen Sie könnten versuchen ,
f.flush()
undos.fsync()
die Datei schreiben und den freien Speicher zu zwingen;quelle
f.flush(); os.fsync()
könnte vielleicht das Schreiben eines freien Speichers erzwingen.os.fsync(f.fileno())
def DownloadFile(url)