版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
《疯狂pthon讲义》第15章的一个多线程下载脚本。
实现多线程下载功能。
原本代码:
#!usr/bin/env python3.6
#encoding:utf-8
'''
author:shadow
datetime:2019/10/14
explain:
测试用例
多线程
下载
'''
import threading
from urllib.request import *
class DownThread(threading.Thread):
def __init__(self, path,start_pos, current_part_size, current_part):
super().__init__()
self.path = path
self.start_pos = start_pos
self.current_part_size = current_part_size
self.current_part = current_part
self.length = 0
def run(self):
req = Request(url = self.path, method='GET')
req.add_header('Accept', '*/*')
req.add_header('Charset', 'UTF-8')
req.add_header('Connection', 'Keep-Alive')
#打开下载资源
f = urlopen(req)
for i in range(self.start_pos):
f.read(1)
while self.length<self.current_part_size:
data = f.read(1024)
if data is None or len(data)<=0:
break
self.current_part.write(data)
self.length+=len(data)
self.current_part.close()
f.close()
class DownLoadUnit:
def __init__(self, path, target_file, thread_num):
self.path = path
self.thread_num = thread_num
self.target_file = target_file
self.threads = []
def download(self):
req = Request(url=self.path,method='GET')
req.add_header('Accept', '*/*')
req.add_header('Charset', 'UTF-8')
req.add_header('Connection', 'Keep-Alive')
#打开下载资源
f = urlopen(req)
#获取要下载的文件大小
self.file_size = int(dict(f.headers).get('Content-Length', 0))
f.close()
#计算每个线程要下载的资源大小
current_part_size = self.file_size // self.thread_num + 1
for i in range(self.thread_num):
#计算每个线程下载的开始位置
start_pos = i * current_part_size
#每个线程都用一个以wb模式打开的文件进行下载
t = open(self.target_file, 'wb')
#定位该线程的下载位置
t.seek(start_pos, 0)
td = DownThread(self.path, start_pos, current_part_size, t)
self.threads.append(td)
td.start()
#获取下载百分比
def get_compete_rate(self):
sum_size = 0
for i in range(self.thread_num):
sum_size+=self.threads[i].length
return sum_size/self.file_size
if __name__ == '__main__':
d = DownLoadUnit("http://www.crazyit.org/data/attachment/forum/201801/19/121212ituj1s9gj8g880jr.png","a.jpg",4)
d.download()
def show_process():
print("已完成:%.2f%%"%d.get_compete_rate())
global c
if d.get_compete_rate()<1:
c=threading.Timer(0.1,show_process)
c.start()
c = threading.Timer(0.1, show_process)
c.start()
难点:实现断点下载
解决方法:增加一个配置文件。