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 threadingimport urllib2import 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