كيف تكتب مؤشر تقدم التنزيل في بايثون؟

StackOverflow https://stackoverflow.com/questions/51212

  •  09-06-2019
  •  | 
  •  

سؤال

أنا أكتب تطبيقًا صغيرًا لتنزيل الملفات عبر http (كما هو موضح على سبيل المثال هنا).

أريد أيضًا تضمين مؤشر تقدم التنزيل الصغير الذي يوضح النسبة المئوية لتقدم التنزيل.

وهنا ما توصلت إليه:

    sys.stdout.write(rem_file + "...")    
    urllib.urlretrieve(rem_file, loc_file, reporthook=dlProgress)

    def dlProgress(count, blockSize, totalSize):
      percent = int(count*blockSize*100/totalSize)
      sys.stdout.write("%2d%%" % percent)
      sys.stdout.write("\b\b\b")
      sys.stdout.flush()

انتاج:اسم الملف الخاص بي...9%

هل هناك أي أفكار أو توصيات أخرى للقيام بذلك؟

الشيء الوحيد المزعج إلى حد ما هو المؤشر الوامض في الجهاز عند الرقم الأول من النسبة المئوية.هل هناك طريقة لمنع هذا؟هل هناك طريقة لإخفاء المؤشر؟

يحرر:

هنا بديل أفضل باستخدام متغير عام لاسم الملف في dlProgress والكود ' ':

    global rem_file # global variable to be used in dlProgress

    urllib.urlretrieve(rem_file, loc_file, reporthook=dlProgress)

    def dlProgress(count, blockSize, totalSize):
      percent = int(count*blockSize*100/totalSize)
      sys.stdout.write("\r" + rem_file + "...%d%%" % percent)
      sys.stdout.flush()

انتاج:اسم الملف الخاص بي...9%

ويظهر المؤشر في نهاية السطر.أفضل بكثير.

هل كانت مفيدة؟

المحلول

توجد مكتبة شريط التقدم النصي للبايثون في http://pypi.python.org/pypi/progressbar/2.2 التي قد تجدها مفيدة:

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

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

وحدة شريط التقدم سهلة الاستخدام للغاية، لكنها قوية جدًا.ويدعم تلقائيًا ميزات مثل تغيير الحجم التلقائي عند توفرها.

نصائح أخرى

يمكنك أيضًا تجربة ما يلي:

sys.stdout.write("\r%2d%%" % percent)
sys.stdout.flush()

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

لما يستحق الأمر، إليك الكود الذي استخدمته لتشغيله:

from urllib import urlretrieve
from progressbar import ProgressBar, Percentage, Bar

url = "http://......."
fileName = "file"
pbar = ProgressBar(widgets=[Percentage(), Bar()])
urlretrieve(url, fileName, reporthook=dlProgress)

def dlProgress(count, blockSize, totalSize):
    pbar.update( int(count * blockSize * 100 / totalSize) )

إذا كنت تستخدم curses الحزمة، لديك سيطرة أكبر بكثير على وحدة التحكم.كما أنه يأتي بتكلفة أعلى من حيث تعقيد التعليمات البرمجية وربما يكون غير ضروري إلا إذا كنت تقوم بتطوير تطبيق كبير يعتمد على وحدة التحكم.

للحصول على حل بسيط، يمكنك دائمًا وضع العجلة الدوارة في نهاية رسالة الحالة (تسلسل الأحرف |, \, -, / والذي يبدو لطيفًا بالفعل تحت المؤشر الوامض.

لقد استخدمت هذا الرمز:

url = (<file location>)
file_name = url.split('/')[-1]
u = urllib2.urlopen(url)
f = open(file_name, 'wb')
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
print "Downloading: %s Bytes: %s" % (file_name, file_size)

file_size_dl = 0
block_sz = 8192
while True:
    buffer = u.read(block_sz)
    if not buffer:
        break

    file_size_dl += len(buffer)
    f.write(buffer)
    status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
    status = status + chr(8)*(len(status)+1)
    print status,

f.close()
def download_progress_hook(count, blockSize, totalSize):
  """A hook to report the progress of a download. This is mostly intended for users with slow internet connections. Reports every 5% change in download progress.
  """
  global last_percent_reported
  percent = int(count * blockSize * 100 / totalSize)

  if last_percent_reported != percent:
    if percent % 5 == 0:
      sys.stdout.write("%s%%" % percent)
      sys.stdout.flush()
    else:
      sys.stdout.write(".")
      sys.stdout.flush()

    last_percent_reported = percent

urlretrieve(url, filename, reporthook=download_progress_hook)

بالنسبة للملفات الصغيرة، قد تحتاج إلى كتابة هذه السطور لتجنب النسب المئوية المجنونة:

sys.stdout.write(" %2d%%" % بالمائة)

sys.stdout.flush()

هتافات

هذه هي الطريقة التي فعلت بها هذا يمكن أن يساعدك:https://github.com/mouuff/MouDownloader/blob/master/api/download.py

تأخرت عن الحفلة كالعادة.فيما يلي تطبيق يدعم الإبلاغ عن التقدم، مثل النواة urlretrieve:

import urllib2

def urlretrieve(urllib2_request, filepath, reporthook=None, chunk_size=4096):
    req = urllib2.urlopen(urllib2_request)

    if reporthook:
        # ensure progress method is callable
        if hasattr(reporthook, '__call__'):
            reporthook = None

        try:
            # get response length
            total_size = req.info().getheaders('Content-Length')[0]
        except KeyError:
            reporthook = None

    data = ''
    num_blocks = 0

    with open(filepath, 'w') as f:
        while True:
            data = req.read(chunk_size)
            num_blocks += 1
            if reporthook:
                # report progress
                reporthook(num_blocks, chunk_size, total_size)
            if not data:
                break
            f.write(data)

    # return downloaded length
    return len(data)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top