Python实现多线程下载文件的代码实例


Posted in Python onJune 01, 2014

实现简单的多线程下载,需要关注如下几点:
1.文件的大小:可以从reponse header中提取,如“Content-Length:911”表示大小是911字节
2.任务拆分:指定各个线程下载的文件的哪一块,可以通过request header中添加“Range: bytes=300-400”(表示下载300~400byte的内容),注意可以请求的文件的range是[0, size-1]字节的。
3.下载文件的聚合:各个线程将自己下载的文件块保存为临时文件,所有线程都完成后,再将这些临时文件按顺序聚合写入到最终的一个文件中。

实现代码:

#!/usr/bin/python
# -*- coding: utf-8 -*-
# filename: paxel.py
# FROM: http://3water.com/code/view/58/full/
# Jay modified it a little and save for further potential usage.'''It is a multi-thread downloading tool
    It was developed following axel.
        Author: volans
        E-mail: volansw [at] gmail.com
'''
import sys
import os
import time
import urllib
from threading import Thread
# in case you want to use http_proxy
local_proxies = {'http': 'http://131.139.58.200:8080'}
 
class AxelPython(Thread, urllib.FancyURLopener):
    '''Multi-thread downloading class.
        run() is a vitural method of Thread.
    '''
    def __init__(self, threadname, url, filename, ranges=0, proxies={}):
        Thread.__init__(self, name=threadname)
        urllib.FancyURLopener.__init__(self, proxies)
        self.name = threadname
        self.url = url
        self.filename = filename
        self.ranges = ranges
        self.downloaded = 0
    def run(self):
        '''vertual function in Thread'''
        try:
            self.downloaded = os.path.getsize(self.filename)
        except OSError:
            #print 'never downloaded'
            self.downloaded = 0
        # rebuild start poind
        self.startpoint = self.ranges[0] + self.downloaded
        # This part is completed
        if self.startpoint >= self.ranges[1]:
            print 'Part %s has been downloaded over.' % self.filename
            return
        self.oneTimeSize = 16384  # 16kByte/time
        print 'task %s will download from %d to %d' % (self.name, self.startpoint, self.ranges[1])
        self.addheader("Range", "bytes=%d-%d" % (self.startpoint, self.ranges[1]))
        self.urlhandle = self.open(self.url)
        data = self.urlhandle.read(self.oneTimeSize)
        while data:
            filehandle = open(self.filename, 'ab+')
            filehandle.write(data)
            filehandle.close()
            self.downloaded += len(data)
            #print "%s" % (self.name)
            #progress = u'\r...'
            data = self.urlhandle.read(self.oneTimeSize)
 
def GetUrlFileSize(url, proxies={}):
    urlHandler = urllib.urlopen(url, proxies=proxies)
    headers = urlHandler.info().headers
    length = 0
    for header in headers:
        if header.find('Length') != -1:
            length = header.split(':')[-1].strip()
            length = int(length)
    return length
 
def SpliteBlocks(totalsize, blocknumber):
    blocksize = totalsize / blocknumber
    ranges = []
    for i in range(0, blocknumber - 1):
        ranges.append((i * blocksize, i * blocksize + blocksize - 1))
    ranges.append((blocksize * (blocknumber - 1), totalsize - 1))
    return ranges
 
def islive(tasks):
    for task in tasks:
        if task.isAlive():
            return True
    return False
 
def paxel(url, output, blocks=6, proxies=local_proxies):
    ''' paxel
    '''
    size = GetUrlFileSize(url, proxies)
    ranges = SpliteBlocks(size, blocks)
    threadname = ["thread_%d" % i for i in range(0, blocks)]
    filename = ["tmpfile_%d" % i for i in range(0, blocks)]
    tasks = []
    for i in range(0, blocks):
        task = AxelPython(threadname[i], url, filename[i], ranges[i])
        task.setDaemon(True)
        task.start()
        tasks.append(task)
    time.sleep(2)
    while islive(tasks):
        downloaded = sum([task.downloaded for task in tasks])
        process = downloaded / float(size) * 100
        show = u'\rFilesize:%d Downloaded:%d Completed:%.2f%%' % (size, downloaded, process)
        sys.stdout.write(show)
        sys.stdout.flush()
        time.sleep(0.5)
    filehandle = open(output, 'wb+')
    for i in filename:
        f = open(i, 'rb')
        filehandle.write(f.read())
        f.close()
        try:
            os.remove(i)
            pass
        except:
            pass
    filehandle.close()
if __name__ == '__main__':
    url = 'http://dldir1.qq.com/qqfile/QQforMac/QQ_V3.1.1.dmg'
    output = 'download.file'
    paxel(url, output, blocks=4, proxies={})
Python 相关文章推荐
python二分法实现实例
Nov 21 Python
详解Python中time()方法的使用的教程
May 22 Python
在Django中管理Users和Permissions以及Groups的方法
Jul 23 Python
Python设置Socket代理及实现远程摄像头控制的例子
Nov 13 Python
使用Python写CUDA程序的方法
Mar 27 Python
python对视频画框标记后保存的方法
Dec 07 Python
Python 实现子类获取父类的类成员方法
Jan 11 Python
python开启debug模式的方法
Jun 27 Python
Python爬虫使用浏览器cookies:browsercookie过程解析
Oct 22 Python
从训练好的tensorflow模型中打印训练变量实例
Jan 20 Python
Python日期格式和字符串格式相互转换的方法
Feb 18 Python
通过实例了解Python异常处理机制底层实现
Jul 23 Python
python使用在线API查询IP对应的地理位置信息实例
Jun 01 #Python
pip 错误unused-command-line-argument-hard-error-in-future解决办法
Jun 01 #Python
2款Python内存检测工具介绍和使用方法
Jun 01 #Python
使用Python的Supervisor进行进程监控以及自动启动
May 29 #Python
python应用程序在windows下不出现cmd窗口的办法
May 29 #Python
python正则表达式re模块详细介绍
May 29 #Python
在python中的socket模块使用代理实例
May 29 #Python
You might like
图书管理程序(三)
2006/10/09 PHP
jQuery Ajax文件上传(php)
2009/06/16 Javascript
javascript中的prototype属性实例分析说明
2010/08/09 Javascript
document.getElementById介绍
2011/09/13 Javascript
使用Jquery实现点击文字后变成文本框且可修改
2013/09/21 Javascript
js实现简单的可切换选项卡效果
2015/04/10 Javascript
javascript通过元素id和name直接取得元素的方法
2015/04/28 Javascript
JavaScript点击按钮后弹出透明浮动层的方法
2015/05/11 Javascript
AngularJS动态生成div的ID源码解析
2016/08/29 Javascript
jquery插件ContextMenu设置右键菜单
2017/03/13 Javascript
详解微信小程序审核不通过的解决方法
2018/01/17 Javascript
axios 处理 302 状态码的解决方法
2018/04/10 Javascript
Echarts之悬浮框中的数据排序问题
2018/11/08 Javascript
解决vue跨域axios异步通信问题
2019/04/17 Javascript
JS实现小星星特效
2019/12/24 Javascript
JS图片预加载三种实现方法解析
2020/05/08 Javascript
javascript实现雪花飘落效果
2020/08/19 Javascript
[56:24]DOTA2上海特级锦标赛主赛事日 - 3 胜者组第二轮#1Liquid VS MVP.Phx第二局
2016/03/04 DOTA
Python实现的一个自动售饮料程序代码分享
2014/08/25 Python
Python中几种操作字符串的方法的介绍
2015/04/09 Python
python利用有道翻译实现"语言翻译器"的功能实例
2017/11/14 Python
python协程之动态添加任务的方法
2019/02/19 Python
selenium+Chrome滑动验证码破解二(某某网站)
2019/12/17 Python
Pytorch提取模型特征向量保存至csv的例子
2020/01/03 Python
Django 批量插入数据的实现方法
2020/01/12 Python
python开根号实例讲解
2020/08/30 Python
python 元组和列表的区别
2020/12/30 Python
HTML5 Canvas实现玫瑰曲线和心形图案的代码实例
2014/04/10 HTML / CSS
HTML5实现经典坦克大战坦克乱走还能发出一个子弹
2013/09/02 HTML / CSS
HTML5本地存储之Web Storage详解
2016/07/04 HTML / CSS
html如何对span设置宽度
2019/10/30 HTML / CSS
员工工作表扬信范文
2014/01/13 职场文书
美术学专业求职信
2014/07/23 职场文书
标准大学生职业生涯规划书写作指南
2014/09/18 职场文书
Nginx 过滤静态资源文件的访问日志的实现
2021/03/31 Servers
如何更改Win11声音输出设备?Win11声音输出设备四种更改方法
2022/04/08 数码科技