Kaip įkelti „python“ didelį failą iš request.py?

Prašymai yra tikrai gera biblioteka. Norėčiau jį naudoti dideliems failams atsisiųsti (> 1 GB). Problema ta, kad neįmanoma išsaugoti viso failo atmintyje. Man reikia jį perskaityti. Ir tai yra problema su šiuo kodu.

 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 

Dėl kokios nors priežasties tai neveikia. Prieš išsaugodamas failą, jis vis dar įkelia atsakymą į atmintį.

189
22 мая '13 в 17:47 2013-05-22 17:47 Roman Podlinov yra nustatytas gegužės 22 d. 13 val. 17:47 2013-05-22 17:47
@ 4 atsakymai

Supratau, kad reikia pakeisti. Triukas buvo nustatyti stream = True get() metodą.

Po to, kai šis pythono procesas sustabdytas atminties (apie 30kb lieka nepaisant įkrovos failo dydžio).

Ačiū @ danodonovan už sintaksę, kurią naudoju čia:

 def download_file(url): local_filename = url.split('/')[-1] # NOTE the stream=True parameter r = requests.get(url, stream=True) with open(local_filename, 'wb') as f: for chunk in r.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks f.write(chunk) #f.flush() commented by recommendation from JFSebastian return local_filename 

Norėdami gauti daugiau informacijos, žr. Http://docs.python-requests.org/en/latest/user/advanced/#body-content-workflow .

389
22 мая '13 в 18:52 2013-05-22 18:52 atsakymas pateikiamas Roman Podlinov gegužės 22 d. 13 val. 18:52 18:52

Tai yra daug lengviau, jei naudojate „ Response.raw ir „ shutil.copyfileobj() :

 import requests import shutil def download_file(url): local_filename = url.split('/')[-1] r = requests.get(url, stream=True) with open(local_filename, 'wb') as f: shutil.copyfileobj(r.raw, f) return local_filename 

Šis failas įeina į diską be pernelyg didelės atminties, o kodas yra paprastas.

44
30 авг. John Zwinck atsakymas 30 rug . 2016-08-30 05:13 '16 at 5:13 2016-08-30 05:13

Jūsų gabalo dydis gali būti per didelis, bandėte jį ištrinti - galbūt 1024 baitų vienu metu? (taip pat galite naudoti, with norite pašalinti sintaksę)

 def DownloadFile(url): local_filename = url.split('/')[-1] r = requests.get(url) with open(local_filename, 'wb') as f: for chunk in r.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks f.write(chunk) return 

Beje, kaip jūs padarėte išvadą, kad atsakymas buvo įkeltas į atmintį?

Tai skamba kaip python nėra flush duomenis į failą, iš kitų SO klausimus galite pabandyti f.flush() ir os.fsync() priversti failą rašyti ir laisvos atminties;

  with open(local_filename, 'wb') as f: for chunk in r.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks f.write(chunk) f.flush() os.fsync(f.fileno()) 
30
22 мая '13 в 18:02 2013-05-22 18:02 atsakymas pateikiamas danodonovan gegužės 22 d. 13 val. 02:02 2013-05-22 18:02

Ne būtent tai, ką paklausė OP, bet ... tai yra juokingai lengva su urllib :

 from urllib.request import urlretrieve url = 'http://mirror.pnl.gov/releases/16.04.2/ubuntu-16.04.2-desktop-amd64.iso' dst = 'ubuntu-16.04.2-desktop-amd64.iso' urlretrieve(url, dst) 

Arba, jei norite įrašyti jį į laikiną failą:

 from urllib.request import urlopen from shutil import copyfileobj from tempfile import NamedTemporaryFile url = 'http://mirror.pnl.gov/releases/16.04.2/ubuntu-16.04.2-desktop-amd64.iso' with urlopen(url) as fsrc, NamedTemporaryFile(delete=False) as fdst: copyfileobj(fsrc, fdst) 

Peržiūrėjau procesą:

 watch 'ps -p 18647 -o pid,ppid,pmem,rsz,vsz,comm,args; ls -al *.iso' 

Ir pamačiau, kad failas augo, tačiau atminties naudojimas liko 17 MB. Ar kažką praleidau?

11
06 июня '17 в 1:13 2017-06-06 01:13 atsakymas pateikiamas x-yuri birželio 06 '17, 13:13 2017-06-06 01:13

Kiti klausimai apie žymes arba Ask a question