python多线程http下载实现示例

 更新时间:2013年12月30日 09:17:14   作者:  
python多线程http下载实现示例,大家参考使用吧

测试平台 Ubuntu 13.04 X86_64 Python 2.7.4

花了将近两个小时, 问题主要刚开始没有想到传一个文件对象到线程里面去, 导致下载下来的文件和源文件MD5不一样,浪费不少时间.

有兴趣的同学可以拿去加上参数,改进下, 也可以加上断点续传.

复制代码 代码如下:

# -*- coding: utf-8 -*-
# Author: ToughGuy
# Email: wj0630@gmail.com
# 写这玩意儿是为了初步了解下python的多线程机制
# 平时没写注释的习惯, 这次花时间在代码里面写上注释也是希望有问题的地方请各位指正, 因为可能我自己也没弄明白.
# 测试平台 Ubuntu 13.04 X86_64 Python 2.7.4

import threading
import urllib2
import sys

max_thread = 10
# 初始化锁
lock = threading.RLock()

class Downloader(threading.Thread):
    def __init__(self, url, start_size, end_size, fobj, buffer):
        self.url = url
        self.buffer = buffer
        self.start_size = start_size
        self.end_size = end_size
        self.fobj = fobj
        threading.Thread.__init__(self)

    def run(self):
        """
            马甲而已
        """
        with lock:
            print 'starting: %s' % self.getName()
        self._download()

    def _download(self):
        """
            我才是搬砖的
        """
        req = urllib2.Request(self.url)
        # 添加HTTP Header(RANGE)设置下载数据的范围
        req.headers['Range'] = 'bytes=%s-%s' % (self.start_size, self.end_size)
        f = urllib2.urlopen(req)
        # 初始化当前线程文件对象偏移量
        offset = self.start_size
        while 1:
            block = f.read(self.buffer)
            # 当前线程数据获取完毕后则退出
            if not block:
                with lock:
                    print '%s done.' % self.getName()
                break
            # 写如数据的时候当然要锁住线程
            # 使用 with lock 替代传统的 lock.acquire().....lock.release()
            # 需要python >= 2.5
            with lock:
                sys.stdout.write('%s saveing block...' % self.getName())
                # 设置文件对象偏移地址
                self.fobj.seek(offset)
                # 写入获取到的数据
                self.fobj.write(block)
                offset = offset + len(block)
                sys.stdout.write('done.\n')


def main(url, thread=3, save_file='', buffer=1024):
    # 最大线程数量不能超过max_thread
    thread = thread if thread <= max_thread else max_thread
    # 获取文件的大小
    req = urllib2.urlopen(url)
    size = int(req.info().getheaders('Content-Length')[0])
    # 初始化文件对象
    fobj = open(save_file, 'wb')
    # 根据线程数量计算 每个线程负责的http Range 大小
    avg_size, pad_size = divmod(size, thread)
    plist = []
    for i in xrange(thread):
        start_size = i*avg_size
        end_size = start_size + avg_size - 1
        if i == thread - 1:
            # 最后一个线程加上pad_size
            end_size = end_size + pad_size + 1
        t = Downloader(url, start_size, end_size, fobj, buffer)
        plist.append(t)

    #  开始搬砖
    for t in plist:
        t.start()

    # 等待所有线程结束
    for t in plist:
        t.join()

    # 结束当然记得关闭文件对象
    fobj.close()
    print 'Download completed!'

if __name__ == '__main__':
    url = 'http://192.168.1.2:8082/downloads/10M.zip'
    main(url=url, thread=10, save_file='test.iso', buffer=4096)

相关文章

  • python中使用pymssql库操作MSSQL数据库

    python中使用pymssql库操作MSSQL数据库

    这篇文章主要给大家介绍了关于python中使用pymssql库操作MSSQL数据库的相关资料,最近在学习python,发现好像没有对pymssql的详细说明,于是乎把官方文档学习一遍,重要部分做个归档,方便以后查阅,需要的朋友可以参考下
    2023-08-08
  • 深入理解Python虚拟机中描述器的实现原理

    深入理解Python虚拟机中描述器的实现原理

    这篇文章主要给大家介绍一个我们在使用类的时候经常使用但是却很少在意的黑科技——描述器的实现原理,文中的示例代码讲解详细,需要的可以参考一下
    2023-05-05
  • python常见排序算法基础教程

    python常见排序算法基础教程

    这篇文章主要为大家详细介绍了python算法的基础教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • python 并发编程 阻塞IO模型原理解析

    python 并发编程 阻塞IO模型原理解析

    这篇文章主要介绍了python 并发编程 阻塞IO模型原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • python list 查询是否存在并且并返回下标的操作

    python list 查询是否存在并且并返回下标的操作

    这篇文章主要介绍了python list 查询是否存在并且并返回下标的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-05-05
  • pytorch加载预训练模型与自己模型不匹配的解决方案

    pytorch加载预训练模型与自己模型不匹配的解决方案

    这篇文章主要介绍了pytorch加载预训练模型与自己模型不匹配的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-05-05
  • 使用python数据清洗代码实例

    使用python数据清洗代码实例

    这篇文章主要介绍了使用python数据清洗代码实例,分享一下近期用python做数据清洗汇总的相关代码,这里我们用到的python包有pandas、numpy、os等,需要的朋友可以参考下
    2023-07-07
  • Python从使用线程到使用async/await的深入讲解

    Python从使用线程到使用async/await的深入讲解

    Python在3.5版本中引入了关于协程的语法糖async和await,所以下面这篇文章主要给大家介绍了关于Python从使用线程到使用async/await的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-09-09
  • python实现TCP服务器端与客户端的方法详解

    python实现TCP服务器端与客户端的方法详解

    这篇文章主要介绍了python实现TCP服务器端与客户端的方法,以实例形式详解分析了Python实现服务器端与客户端的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-04-04
  • python如何查看微信消息撤回

    python如何查看微信消息撤回

    这篇文章主要为大家详细介绍了python实现查看微信消息撤回的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11

最新评论