【问题标题】:Find the speed of download for a progressbar查找进度条的下载速度
【发布时间】:2016-06-11 05:21:34
【问题描述】:

我正在编写一个脚本来从网站下载视频。我添加了一个报告挂钩来获取下载进度。因此,到目前为止,它显示了下载数据的百分比和大小。我认为添加下载速度和 eta 会很有趣。
问题是,如果我使用简单的speed = chunk_size/time,显示的速度足够准确,但会像疯了一样跳来跳去。因此,我使用了下载单个块所用时间的历史记录。类似speed = chunk_size*n/sum(n_time_history).
现在它显示出稳定的下载速度,但它肯定是错误的,因为它的值以几比特/秒为单位,而下载的文件明显以更快的速度增长。
有人可以告诉我哪里出错了吗?

这是我的代码。

def dlProgress(count, blockSize, totalSize):
    global init_count
    global time_history
    try:
        time_history.append(time.monotonic())
    except NameError:
        time_history = [time.monotonic()]
    try:
        init_count
    except NameError:
        init_count = count
    percent = count*blockSize*100/totalSize
    dl, dlu = unitsize(count*blockSize)             #returns size in kB, MB, GB, etc.
    tdl, tdlu = unitsize(totalSize)
    count -= init_count                             #because continuation of partial downloads is supported
    if count > 0:
        n = 5                                       #length of time history to consider
        _count = n if count > n else count
        time_history = time_history[-_count:]
        time_diff = [i-j for i,j in zip(time_history[1:],time_history[:-1])]
        speed = blockSize*_count / sum(time_diff)
    else: speed = 0
    n = int(percent//4)
    try:
        eta = format_time((totalSize-blockSize*(count+1))//speed)
    except:
        eta = '>1 day'
    speed, speedu = unitsize(speed, True)           #returns speed in B/s, kB/s, MB/s, etc.
    sys.stdout.write("\r" + percent + "% |" + "#"*n + " "*(25-n) + "| " + dl + dlu  + "/" + tdl + tdlu + speed + speedu + eta)
    sys.stdout.flush()

编辑:
更正了逻辑。现在显示的下载速度要好得多。
随着我增加用于计算速度的历史记录长度,稳定性会增加,但不会显示速度的突然变化(如果下载停止等)。
我如何使它稳定,但对大的变化敏感?

我意识到这个问题现在更面向数学,但如果有人能帮助我或为我指明正确的方向,那就太好了。
另外,请告诉我是否有更有效的方法来完成此操作。

【问题讨论】:

  • p=30speed = chunk_size*n/sum(n_time_history) if n<p else chunk_size*p/sum(n_time_history[-p:]) 怎么样,否则你希望 p 成为
  • @TomaszPlaskota 这和我在代码中所做的不一样吗?
  • 我的错,只是在看你描述的逻辑。由于您已经这样做了,因此可以通过对时间范围进行分组(即 0-30、30-60、60-90 或您喜欢的 w/e 间隔),然后从该集合中去除最低/最高平均值,并计算得出更好的估计值大约没有那些极端的时间。或者使用任何其他统计过滤方法代替最小值/最大值。编辑:为了使其对最近的变化敏感,引入了一些随着时间推移而减少的权重。
  • 谢谢。没有考虑过重。至于你建议的其他内容,我的数学太糟糕了,无法理解,但我会照样研究它们。

标签: python performance python-3.x download urllib


【解决方案1】:
_count = n if count > n else count
time_history = time_history[-_count:]
time_weights = list(range(1,len(time_history))) #just a simple linear weights
time_diff = [(i-j)*k for i,j in zip(time_history[1:], time_history[:-1],time_weights)]
speed = blockSize*(sum(time_weights)) / sum(time_diff)

为了使它更稳定并且在下载高峰或下降时不做出反应,您也可以添加以下内容:

_count = n if count > n else count
time_history = time_history[-_count:]
time_history.remove(min(time_history))
time_history.remove(max(time_history))
time_weights = list(range(1, len(time_history))) #just a simple linear weights
time_diff = [(i-j)*k for i,j in zip(time_history[1:], time_history[:-1],time_weights)]
speed = blockSize*(sum(time_weights)) / sum(time_diff)

这将消除time_history 中的最高和最低峰值,这将使数字显示更加稳定。如果您想挑剔,您可能可以在删除之前生成权重,然后使用time_diff.index(min(time_diff)) 过滤映射值。

同时使用非线性函数(如sqrt())来生成权重会给你带来更好的结果。哦,正如我在 cmets 中所说:将统计方法添加到过滤时间应该稍微好一些,但我怀疑它不值得增加开销。

【讨论】:

  • 非常感谢!有时间我会试试的。顺便说一句,您的代码中有错误。它应该是 time_diff = [(i-j)*k for i,j,k in zip(time_history[1:], time_history[:-1],time_weights)] 而不是 time_diff = [(i-j)*time_weights[i] for i,j in zip(time_history[1:], time_history[:-1])]。因为time_history 中的值不完全是time_weights 的索引值。
  • 如果我的数学是正确的,speed = blockSize*sum(time_weights) / sum(time_diff)
  • 哈哈你显然是对的,当我脑子里有这么多东西的时候不应该写答案,但这看起来很有趣。我太习惯了 i,j,k 是索引并避免使用实际对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-26
  • 2018-01-08
  • 2012-03-01
  • 2013-03-16
相关资源
最近更新 更多