【问题标题】:How to count how many data has been downloaded in the last second? (FTP)如何统计上一秒下载了多少数据? (FTP)
【发布时间】:2019-09-13 13:08:20
【问题描述】:

我想知道在过去 1 秒内下载了多少数据。
我还没有代码,但我想知道什么时候应该开始计算这 1 秒,然后怎么做。
我应该在retrbinary() 之前还是之后开始计数?还是我完全错了?

【问题讨论】:

  • 你能把下载文件的代码贴出来吗?
  • 通常你有一个循环读取x字节的数据量,只需检查每次迭代(或十次或其他)需要多长时间,然后进行计算
  • 这看起来像XY problem。我假设您真正想要实现的是传输速度显示。
  • @Artog 循环如何工作?假设我有这行代码:ftp.retrbinary('RETR ' + readme.txt, 8192) 我在哪里循环 x 字节数? @MartinPrikryl,是的,我想实现传输速度显示。

标签: python python-3.x download ftp ftplib


【解决方案1】:

首先,传输进度显示有现成的实现,包括传输速度。

例如,progressbar2 模块。见Show FTP download progress in Python (ProgressBar)

progressbar2 默认显示FileTransferSpeed widget,即下载开始后的平均传输速度。

但请注意,速度显示器通常不会显示这样的速度。它们显示过去几秒钟的平均速度。这使得该值更具信息性。 progressbar2 有 AdaptiveTransferSpeed widget 。但它seems to be broken


如果您想自己实现计算,并且对自下载开始以来的简单平均传输速度感到满意,这很容易:

from ftplib import FTP
import time
import sys
import datetime

ftp = FTP(host, user, passwd)

print("Downloading")
total_length = 0
start_time = datetime.datetime.now()

def write(data):
   f.write(data)
   global total_length
   global start_time
   total_length += sys.getsizeof(data)
   elapsed = (datetime.datetime.now() - start_time)
   speed = (total_length / elapsed.total_seconds())
   print("\rElapsed: {0} Speed: {1:.2f} kB/s".format(str(elapsed), speed / 1024), end="")

f = open('file.dat', 'wb')
ftp.retrbinary("RETR /file.dat", write)
f.close()

print()
print("done")    

最后几秒的平均速度更难计算。您必须记住过去时刻传输的数据量。从AdaptiveTransferSpeed 窃取(并修复)代码,你会得到类似的东西:

sample_times = []
sample_values = []
INTERVAL = datetime.timedelta(milliseconds=100)
last_update_time = None
samples=datetime.timedelta(seconds=2)
total_length = 0

def write(data):
   f.write(data)

   global total_length

   total_length += sys.getsizeof(data)
   elapsed = (datetime.datetime.now() - start_time)

   if sample_times:
       sample_time = sample_times[-1]
   else:
       sample_time = datetime.datetime.min

   t = datetime.datetime.now()
   if t - sample_time > INTERVAL:
       # Add a sample but limit the size to `num_samples`
       sample_times.append(t)
       sample_values.append(total_length)

       minimum_time = t - samples
       minimum_value = sample_values[-1]
       while (sample_times[2:] and
              minimum_time > sample_times[1] and
              minimum_value > sample_values[1]):
           sample_times.pop(0)
           sample_values.pop(0)

   delta_time = sample_times[-1] - sample_times[0]
   delta_value = sample_values[-1] - sample_values[0]
   if delta_time:
       speed = (delta_value / delta_time.total_seconds())

       print("\rElapsed: {0} Speed: {1:.2f} kB/s".format(
           str(elapsed), speed / 1024), end="")

ftp.retrbinary("RETR /medium.dat", write)

【讨论】:

  • 等等,什么是即时速度?您的代码正在运行,但我不明白什么是“即时速度”。我的目标是创建一个传输速度显示,就像您在 Steam 上下载游戏或在 Chrome 中下载文件时一样,它会显示当前的下载速度。那是即时速度还是平均传输速度?
  • 代码计算bytes-downloaded-since-start/second-since-start。我不知道 Steam 算法是什么,但我相信大多数速度显示器都会执行类似 bytes-downloaded-in-last-X-seconds/X 的操作。 X 大概是 2-5 秒。 AdaptiveTransferSpeed widget from progressbar2 library 默认使用X=2
  • 如果它显示 bytes-downloaded-since-start/seconds-since-starts 那么为什么当我下载 102 MB 文件时它显示它下载了 3500 kB?
  • 我不明白。我的代码在kB/s 中显示速度,而不是在kB 中显示的下载字节数。
  • 我的也是这样,但你说它是bytes-downloaded-since-start。它也在我的控制台中显示kB/s,但正如你所说,这些是自开始以来下载的字节数?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-03
  • 1970-01-01
  • 2014-08-16
  • 2018-03-11
  • 2011-01-17
  • 1970-01-01
相关资源
最近更新 更多