【问题标题】:How to write a download progress indicator in Python?如何在 Python 中编写下载进度指示器?
【发布时间】:2010-09-08 05:59:49
【问题描述】:

我正在编写一个小应用程序来通过 http 下载文件(例如,描述为 here)。

我还想包含一个小的下载进度指示器,显示下载进度的百分比。

这是我想出的:

sys.stdout.write(rem_file + "...") urllib.urlretrieve(rem_file,loc_file,reporthook=dlProgress) def dlProgress(计数,块大小,总大小): 百分比 = int(count*blockSize*100/totalSize) sys.stdout.write("%2d%%" % percent) sys.stdout.write("\b\b\b") sys.stdout.flush()

输出:我的文件名... 9%

还有其他想法或建议吗?

有点烦人的是终端中百分比的第一个数字上的闪烁光标。有没有办法防止这种情况?有没有办法隐藏光标?

编辑:

在 dlProgress 和 '\r' 代码中使用全局变量作为文件名的更好选择:

global rem_file # 在 dlProgress 中使用的全局变量 urllib.urlretrieve(rem_file,loc_file,reporthook=dlProgress) def dlProgress(计数,块大小,总大小): 百分比 = int(count*blockSize*100/totalSize) sys.stdout.write("\r" + rem_file + "...%d%%" % percent) sys.stdout.flush()

输出:我的文件名...9%

光标出现在行的末尾。好多了。

【问题讨论】:

  • global rem_file 仅在将其绑定到新对象 rem_file = ... 的函数中才有意义,否则(如果您只读取其值)global rem_file 是不必要的。
  • 您也可以在标准输出上执行 /r + flush()。我只是根据您提到的终端行为猜测这是在 Windows 中运行的。

标签: python http


【解决方案1】:

http://pypi.python.org/pypi/progressbar/2.2 有一个 Python 文本进度条库,您可能会发现它很有用:

这个库提供了一个文本模式的进度条。这通常用于显示长时间运行的操作的进度,提供正在进行处理的视觉线索。

ProgressBar 类管理进度,行的格式由许多小部件给出。小部件是一个对象,可能会根据进度状态以不同方式显示。有三种类型的小部件: - 一个字符串,它总是显示自己; - 一个 ProgressBarWidget,每次调用 update 方法时可能返回不同的值;和 - ProgressBarWidgetHFill,它类似于 ProgressBarWidget,只是它会扩展以填充行的剩余宽度。

进度条模块非常易于使用,但功能非常强大。并自动支持可用时自动调整大小等功能。

【讨论】:

  • 如果在单独的线程中提示多个下载,如何在终端中显示多个进度条?
【解决方案2】:

你也可以试试:

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

在字符串的开头使用单个回车而不是多个退格。您的光标仍会闪烁,但它会在百分号之后而不是第一个数字下方闪烁,并且使用一个控制字符而不是三个控制字符可能会减少闪烁。

【讨论】:

    【解决方案3】:

    对于它的价值,这是我用来让它工作的代码:

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

    【讨论】:

    • 这只给了我:pbar.update(int(count * blocksize * 100 / totalSize)) NameError: global name 'blocksize' is not defined
    • 这是一个错字。它应该是输入参数。我已经更新了答案以反映这一点。谢谢!
    【解决方案4】:

    如果您使用curses 包,您可以更好地控制控制台。它还以更高的代码复杂性为代价,除非您正在开发基于控制台的大型应用程序,否则可能没有必要。

    对于一个简单的解决方案,您始终可以将纺车放在状态消息的末尾(字符序列|, \, -, / 在闪烁的光标下实际上看起来不错。

    【讨论】:

      【解决方案5】:

      我使用了这个代码:

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

      【讨论】:

        【解决方案6】:
        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)
        

        【讨论】:

          【解决方案7】:

          对于小文件,您可能需要这些行以避免疯狂的百分比:

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

          sys.stdout.flush()

          干杯

          【讨论】:

            【解决方案8】:

            我就是这样做的,这可以帮助你: https://github.com/mouuff/MouDownloader/blob/master/api/download.py

            【讨论】:

              【解决方案9】:

              聚会迟到了,像往常一样。这是一个支持报告进度的实现,例如核心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)
              

              【讨论】:

                猜你喜欢
                • 2012-11-08
                • 2018-04-27
                • 1970-01-01
                • 2021-02-17
                • 1970-01-01
                • 1970-01-01
                • 2012-04-22
                • 2014-03-05
                相关资源
                最近更新 更多