【Python-利用动态二维码传输文件(七)】计算文件传输速度,以KB/s形式显示在Tkinter界面。

        上一篇文章实现了动态二维码文件接收端的基本功能,但只能显示接收数据的完成度,不能显示接收速度,本篇文章研究怎么计算文件传输速度,并以KB/s形式显示在Tkinter界面,方便以后调试和优化代码。

 

一、程序效果展示

        可以看到右下角有统计发送速度的状态栏,传输速度约为1.3kb/s,还是挺慢的,还需要继续优化代码提高效率。

【Python-利用动态二维码传输文件(七)】计算文件传输速度,以KB/s形式显示在Tkinter界面。_第1张图片


 二、程序设计原理

        (一)搞清楚文件大小的统计单位

        编程前应先弄明白Byte、KB、MB、GB之间的关系,有兴趣可以看看这篇文章的一些基本概念,辅助设计合理可靠的算法。

        文件大小的统计单位参考文章↓↓↓
位(bit)、字节(Byte)、KB、MB、GB、TB之间的换算关系_爱学习的哆啦A梦的博客-CSDN博客_bit byte换算bit(位,又名“比特”):bit的缩写是b,是计算机运算的基础,属于二进制的范畴。通常用bit来作数据传输的单位,因为物理层,数据链路层的传输对于用户是透明的,而这种通信传输是基于二进制的传输。Byte(字节):Byte的缩写是B,是计算机文件大小的基本计算单位。在应用层通常是用Byte来作单位,表示文件的大小,在用户看来就是可见的数据大小。比如一个字符就是1Byte,如果是汉字,则是2By...https://blog.csdn.net/weixin_44232308/article/details/87062271?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%AD%97%E8%8A%82%E8%BD%AC%E6%8D%A2kb%E3%80%81mb%E3%80%81gb%E3%80%81tb&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-87062271.nonecase&spm=1018.2226.3001.4187

        这里引用这篇文章的图简单说明它们之间的关系,由于动态二维码发送文件的速度很慢,目前自己写的程序速度大概为:小文件能到2~3KB/每秒,大文件只能到1~1.5KB/每秒。因此到KB就够用了,还没到MB级别,只需重点实现bit、ByteKB之间的转换即可。

【Python-利用动态二维码传输文件(七)】计算文件传输速度,以KB/s形式显示在Tkinter界面。_第2张图片   


        (二)搞清楚不同单位的转换,并使用Pythonsys.getsizeof()函数计算对象内存大小 

        getsizeof()只计算实际使用的内存大小,引用所消耗的内存大小不计算。经过上图计算可以得到以下转换公式。

        1Byte(字节)=8b(位)
        1 KB = 1024 B
        1 MB = 1024 KB

        sys.getsizeof()返回的是Byte的数量。因此使用sys.getsizeof(_str)/1024,可以得到KB的数量。

        以下代码实现循环截图,并统计累计接收数据的大小。其中_qr_set_size = _qr_set_size + sys.getsizeof(_str) / 1024实现累加统计数据量的大小。为什么不直接使用sys.getsizeof(_qr_set)统计set对象的大小呢,因为经过测试,当set对象内存不足的时候会自动提前扩大set内存,而且不是按实际大小扩容,所以统计set对象的内容并不能得到累加数据量的大小

# 当_stop_flag为False,一直循环截图
_stop_flag[0] = False
# 统计接收速度,_qr_set_size为目前接收数据量的大小
_qr_set_size = 0
# _qr_set用于存放每帧识别出来的二维码信息,set数据结构用于存放不重复数据,对存入的数据会自动去重
_qr_set = set()
# 使用pyautogui.screenshot()对屏幕截图
while _stop_flag[0] is False:
    _screenshot_img = pyautogui.screenshot()
    # 把Pillow图片对象转换为numpy图片对象
    _numpy_img = numpy.array(_screenshot_img)
    # 将图像灰度化提高识别效率
    _cvt_image = cv2.cvtColor(_numpy_img, cv2.COLOR_BGR2GRAY)
    # 解析二维码中的数据
    _qr_data = pyzbar.decode(_cvt_image)
    # 判断二维码是否识别成功,若识别成功,识别数据的长度_data_len应大于0
    if _data_len > 0:
        # 把识别出来的单张二维码图片信息存入_qr_set中
        _str = _qr_data[0].data.decode('utf-8')
        _qr_set.add(_str)
        # 统计累计接收数据大小
        _qr_set_size = _qr_set_size + sys.getsizeof(_str) / 1024

 sys.getsizeof()的参考文章↓↓↓

python-sys.getsizeof的使用_我是乔木的博客-CSDN博客_sys.getsizeof科班出身的码畜一直被灌输一条上帝圣经:“一个int占4个字节,一个char占1个字节,一个float占4个字节。。。”,今天看下了python的getsizeof函数,发现python中各个基本数据类型(对象)占用的内存大小和c++/Java完全不一样~前提概述:python中一切都是对象,so python中其实根本不存在int float这些类型,int其实是一个python对象...https://blog.csdn.net/qm5132/article/details/100557950


(三)计算每次累加数据的时间间隔,使用公式得出传输速度

        设当前累计接收的文件大小为_qr_set_size,用q代表

        设每次向set对象添加数据的时间间隔为_time_span,用t代表

        设文件传输的速度为_label_speed_text,用s代表

        那计算文件传输的公式为:s= \frac{q}{t},Python代码如下:

# 接收开始时间
_start_time = time.time()
#某操作
#某操作
#某操作

# 获取当前时间time.time(),减去开始时间_start_time,使用round保留两位小数
_time_span = round(time.time() - _start_time, 2)

# 设置Tkinter Label
_label_speed_text.set("%.2fkb/s" % (_qr_set_size / _time_span))

 三、完整源代码

# 使用OpenCV库连续截图,并逐张识别出二维码信息
def save_qrs(_tk, _progressbar, _label_progress_text, _stop_flag, _label_filepath_text, _label_speed_text):
    # _qr_set用于存放每帧识别出来的二维码信息,set数据结构用于存放不重复数据,对存入的数据会自动去重
    _qr_set = set()
    # 设置进度条默认长度为100
    _pb_len = 100
    # 统计接收速度,_qr_set_size为目前接收数据量的大小
    _qr_set_size = 0
    # 当_stop_flag为False,一直循环截图
    i = 0
    _stop_flag[0] = False
    # 接收开始时间
    _start_time = time.time()
    while _stop_flag[0] is False:
        # 使用pyautogui.screenshot()对屏幕截图
        _screenshot_img = pyautogui.screenshot()
        # 把Pillow图片对象转换为numpy图片对象
        _numpy_img = numpy.array(_screenshot_img)
        # 将图像灰度化提高识别效率
        _cvt_image = cv2.cvtColor(_numpy_img, cv2.COLOR_BGR2GRAY)
        # 解析二维码中的数据
        _qr_data = pyzbar.decode(_cvt_image)
        # 统计接收进度,_qr_set_len为目前接收的不重复的二维码信息数
        _qr_set_len = len(_qr_set)
        # _data_len为单张二维码图片识别后数据的长度用于判断二维码是否识别成功,识别不成功长度为0
        _data_len = len(_qr_data)
        # 更新界面状态栏状态,如:正在接收,[11/51]
        _label_progress_text.set("正在接收,[%d/%d]" % (_qr_set_len, _pb_len))
        # 判断二维码是否识别成功,若识别成功,识别数据的长度_data_len应大于0
        if _data_len > 0:
            _str = _qr_data[0].data.decode('utf-8')
            # 把识别出来的单张二维码图片信息存入_qr_set中
            _qr_set.add(_str)
            _qr_set_len_now = len(_qr_set)
            if _qr_set_len_now != _qr_set_len:
                _qr_set_size = _qr_set_size + sys.getsizeof(_str) / 1024
            _time_span = round(time.time() - _start_time, 2)
            _label_speed_text.set("%.2fkb/s" % (_qr_set_size / _time_span))
            if _qr_set_len == 0:
                # 用于更新进度条长度_pb_len,只在接收第一次数据时更新长度提高效率
                # 接收数据的格式如:[1/51]xsdgsiakghalshg,获取51存入_pd_len
                _str1 = _str.split(']')
                _str2 = _str1[0].split('/')
                _pb_len = int(_str2[1])
                _progressbar["maximum"] = _pb_len
            # 更新进度条进度
            _progressbar["value"] = _qr_set_len
        if _qr_set_len == _pb_len:
            # 全部数据接收完毕跳出循环
            break
        _tk.update()
    i = i + 1

    if _stop_flag[0] is False:
        # 调用合并函数
        regroup(_qr_set, _label_filepath_text)
        _label_progress_text.set("已完成接收")
    else:
        _label_progress_text.set("已暂停")

你可能感兴趣的:(python,二维码,python,二维码,tkinter,进度条,文件传输)