stream - كيفية تنزيل ملف كبير في python مع requests.py؟




python-requests (5)

Requests هي مكتبة جميلة حقا. أود استخدامه لتنزيل ملفات كبيرة (> 1GB). المشكلة أنه ليس من الممكن الاحتفاظ بملف كامل في الذاكرة أحتاج لقراءته في قطع. وهذه مشكلة في التعليمة البرمجية التالية

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 

لسبب ما لا يعمل بهذه الطريقة. لا يزال يحمّل الاستجابة في الذاكرة قبل حفظها في ملف.


Answers

أسهل بكثير إذا كنت تستخدم Response.raw و 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

هذا دفق الملف إلى القرص دون استخدام الذاكرة الزائدة ، والرمز بسيط.


قد يكون حجم المقطع كبيرًا جدًا ، هل جرّبت إسقاط ذلك - ربما 1024 بايت في المرة الواحدة؟ (يمكنك أيضًا استخدامه لترتيب البنية)

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 

بالمناسبة ، كيف تستنتج أن الاستجابة قد تم تحميلها في الذاكرة؟

يبدو كما لو python لا تفريغ البيانات إلى ملف ، من أسئلة أخرى SO يمكنك محاولة f.flush() و os.fsync() لفرض كتابة الملف والذاكرة الحرة ؛

    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())

أنا أحسب ما يجب تغييره. كانت الخدعة لتعيين stream = True في طريقة get() .

بعد توقف هذه العملية الثعبان لامتصاص الذاكرة (يبقى حوالي 30kb بغض النظر عن حجم ملف التحميل).

شكرا لكdanodonovan بناء جملة لك يمكنني استخدامه هنا:

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 J.F.Sebastian
    return local_filename

راجع http://docs.python-requests.org/en/latest/user/advanced/#body-content-workflow للحصول على مزيد من المعلومات المرجعية.


ليس بالضبط ما كان يسأل OP ، ولكن ... من السخرية للغاية القيام بذلك مع 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)

أو بهذه الطريقة ، إذا كنت تريد حفظها في ملف مؤقت:

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)

لقد شاهدت العملية:

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

ورأيت الملف ينمو ، ولكن بقي استخدام الذاكرة في 17 ميغابايت. هل فاتني شيء؟


أعتقد أن مقدمة ONLamp إلى برمجة metaclass مكتوبة بشكل جيد وتعطي مقدمة جيدة للموضوع على الرغم من كونها عدة سنوات بالفعل.

http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html (تم أرشفته على https://web.archive.org/web/20080206005253/http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html )

باختصار: الطبقة هي مخطط لإنشاء مثيل ، فالمساح هو مخطط لإنشاء الفصل الدراسي. يمكن أن نرى بسهولة أنه في فصول بيثون يجب أن تكون كائنات من الدرجة الأولى أيضًا لتمكين هذا السلوك.

لم أكتب أبدا نفسي ، لكني أعتقد أنه يمكن رؤية واحدة من ألطف استخدامات metaclasses في إطار Django . تستخدم فئات النماذج منهج metaclass لتمكين أسلوب إعلاني لكتابة نماذج جديدة أو فئات نماذج. أثناء إنشاء الطبقة التدريبية للفصل الدراسي ، يحصل جميع الأعضاء على إمكانية تخصيص الفئة نفسها.

الشيء الذي يبقى ليقوله هو: إذا كنت لا تعرف ما هي metaclasses ، فإن الاحتمال الذي لن تحتاج لهم هو 99 ٪.





python stream python-requests