简体   繁体   English

如何使用请求测量下载速度和进度?

[英]How to measure download speed and progress using requests?

I am using requests to download files, but for large files I need to check the size of the file on disk every time because I can't display the progress in percentage and I would also like to know the download speed.我正在使用requests下载文件,但对于大文件我需要每次检查磁盘上文件的大小,因为我无法以百分比显示进度,我也想知道下载速度。 How can I go about doing it?请问我go怎么办呢? Here's my code:这是我的代码:

import requests
import sys
import time
import os

def downloadFile(url, directory) :
  localFilename = url.split('/')[-1]
  r = requests.get(url, stream=True)

  start = time.clock()
  f = open(directory + '/' + localFilename, 'wb')
  for chunk in r.iter_content(chunk_size = 512 * 1024) :
        if chunk :
              f.write(chunk)
              f.flush()
              os.fsync(f.fileno())
  f.close()
  return (time.clock() - start)

def main() :
  if len(sys.argv) > 1 :
        url = sys.argv[1]
  else :
        url = raw_input("Enter the URL : ")
  directory = raw_input("Where would you want to save the file ?")

  time_elapsed = downloadFile(url, directory)
  print "Download complete..."
  print "Time Elapsed: " + time_elapsed


if __name__ == "__main__" :
  main()

I think one way to do it would be to read the file every time in the for loop and calculate the percentage of progress based on the header Content-Length .我认为一种方法是每次在for循环中读取文件并根据 header Content-Length计算进度百分比。 But that would be again an issue for large files(around 500MB).但这对于大文件(大约 500MB)来说又是一个问题。 Is there any other way to do it?还有其他方法吗?

see here: Python progress bar and downloads请参见此处: Python 进度条和下载

i think the code would be something like this, it should show the average speed since start as bytes per second:我认为代码应该是这样的,它应该以每秒字节数显示自启动以来平均速度

import requests
import sys
import time

def downloadFile(url, directory) :
  localFilename = url.split('/')[-1]
  with open(directory + '/' + localFilename, 'wb') as f:
    start = time.clock()
    r = requests.get(url, stream=True)
    total_length = r.headers.get('content-length')
    dl = 0
    if total_length is None: # no content length header
      f.write(r.content)
    else:
      for chunk in r.iter_content(1024):
        dl += len(chunk)
        f.write(chunk)
        done = int(50 * dl / total_length)
        sys.stdout.write("\r[%s%s] %s bps" % ('=' * done, ' ' * (50-done), dl//(time.clock() - start)))
        print ''
  return (time.clock() - start)

def main() :
  if len(sys.argv) > 1 :
        url = sys.argv[1]
  else :
        url = raw_input("Enter the URL : ")
  directory = raw_input("Where would you want to save the file ?")

  time_elapsed = downloadFile(url, directory)
  print "Download complete..."
  print "Time Elapsed: " + time_elapsed


if __name__ == "__main__" :
  main()

An improved version of the accepted answer for python3 using io.Bytes (write to memory), result in Mbps, support for ipv4 / ipv6 , size and port arguments.使用io.Bytes (写入内存)的 python3 已接受答案的改进版本,结果为 Mbps,支持ipv4 / ipv6 ,大小和端口参数。

def speed_test(size=5, ipv="ipv4", port=80):
    import sys, time, io, requests
    if size == 1024:
        size = "1GB"
    else:
        size = f"{size}MB"

    url = f"http://{ipv}.download.thinkbroadband.com:{port}/{size}.zip"

    with io.BytesIO() as f:
        start = time.clock()
        r = requests.get(url, stream=True)
        total_length = r.headers.get('content-length')
        dl = 0
        if total_length is None: # no content length header
            f.write(r.content)
        else:
            for chunk in r.iter_content(1024):
                dl += len(chunk)
                f.write(chunk)
                done = int(30 * dl / int(total_length))
                sys.stdout.write("\r[%s%s] %s Mbps" % ('=' * done, ' ' * (30-done), dl//(time.clock() - start) / 100000))

    print( f"\n{size} = {(time.clock() - start):.2f} seconds")

Usage Examples:用法示例:

speed_test()
speed_test(10)
speed_test(50, "ipv6")
speed_test(1024, port=8080)

Output Sample:输出样本:

[==============================] 61.34037 Mbps
100MB = 17.10 seconds

Available Options:可用选项:

size: 5, 10, 20, 50, 100, 200, 512, 1024尺寸: 5, 10, 20, 50, 100, 200, 512, 1024

ipv: ipv4, ipv6 ipv: ipv4, ipv6

port: 80, 81, 8080端口: 80, 81, 8080

I had a problem with a specific slow server to download a big file我在使用特定的慢速服务器下载大文件时遇到问题

  1. no Content-Length header.没有内容长度 header。
  2. big file (42GB),大文件(42GB),
  3. no compression,没有压缩,
  4. slow server (<1MB/s),慢速服务器(<1MB/s),

Beeing this big, I had also problem with memory usage during the request.这么大,我在请求期间也遇到了 memory 使用问题。 Requests doesn't write output on file, like urlibs does, looks like it keep it in memory. Requests 没有像 urlibs 那样在文件中写入 output,看起来它保存在 memory 中。

No content length header makes the accepted answer.. not monitoring.没有内容长度 header 作出接受的答案.. 不监控。

So I wrote this -basic- method to monitor speed during the csv download following just the "requests" documentation.因此,我编写了这个 -basic- 方法来监控 csv 下载期间的速度,仅遵循“请求”文档。

It needs a fname (complete output path), a link (http or https) and you can specify custom headers.它需要一个 fname(完整的 output 路径)、一个链接(http 或 https)并且您可以指定自定义标头。

BLOCK=5*1024*1024
try:
    with open(fname, 'wb') as f:
        r = requests.get(link, headers=headers, stream=True)

        ## This is, because official dozumentation suggest it, 
        ## saying it's more reliable thatn cycling directly on iterlines, to don't lose data
        lines = r.iter_lines()

        ## Init the base vars, for monitor and block management
        ## Obj is a byte object, because iterlines returno objects
        tsize = 0; obj = bytearray(); t0=time.time(); i=0;
        for line in lines:

            ## calculate the line size, in bytes, and add to the byte object
            tsize+=len(line)
            obj.extend(line)

            ## When condition reached, 
            if tsize > BLOCK:   
                ## Increment the block number
                i+=1;
                
                ## Calculate the speed.. this is in MB/s, 
                ## but you can easily change to KB/s, or Blocks/s
                t1=time.time()
                t=t1-t0;
                speed=round(5/t, 2);

                ## Write the block to the file.
                f.write(obj)

                ## Write stats
                print('got', i*5, 'MB ', 'block' ,i, ' @', speed,'MB/s')

                ## Reinit all the base vars, for a new block
                obj=bytearray(); tsize=0; t0=time.time()

        ## Write the last block part to the file. 
        f.write(obj)

except Exception as e:
        print("Error: ", e, 0)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM