python多线程http下载实现示例_python

测试平台 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)

时间: 2024-08-02 17:48:21

python多线程http下载实现示例_python的相关文章

python实现爬虫下载漫画示例_python

复制代码 代码如下: #!/usr/bin/python3.2import os,socketimport urllibimport urllib.request,threading,timeimport re,sysglobal manhuaweb,weburl,floder,chapterbegin,currentthreadnum,threadcount,mutex,mutex2 weburl=''floder=''chapterbegin=0currentthreadnum=0threa

python多线程编程方式分析示例详解_python

在Python多线程中如何创建一个线程对象如果你要创建一个线程对象,很简单,只要你的类继承threading.Thread,然后在__init__里首先调用threading.Thread的__init__方法即可 复制代码 代码如下: import threading  class mythread(threading.Thread):  def __init__(self, threadname):  threading.Thread.__init__(self, name = thread

Android多线程断点下载完整示例详解

MainActivity如下: package cc.activity; import java.io.File; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.

python多线程用法实例详解_python

本文实例分析了python多线程用法.分享给大家供大家参考.具体如下: 今天在学习尝试学习python多线程的时候,突然发现自己一直对super的用法不是很清楚,所以先总结一些遇到的问题.当我尝试编写下面的代码的时候: 复制代码 代码如下: class A():     def __init__( self ):         print "A" class B( A ):     def __init__( self ):         super( B, self ).__in

快速排序的算法思想及Python版快速排序的实现示例_python

快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod). 1.分治法的基本思想 分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题.递归地解这些子问题,然后将这些子问题的解组合为原问题的解. 2.快速排序的基本思想 设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为: (1)分解: 在R[low..high]中任选一个记录作为基准(

python爬虫教程之爬取百度贴吧并下载的示例_python

测试url:http://tieba.baidu.com/p/27141123322?pn=begin  1end   4 复制代码 代码如下: import string ,urllib2 def baidu_tieba(url,begin_page,end_page):    for i in range(begin_page, end_page+1):        sName = string.zfill(i,5)+ '.html'        print '正在下载第' + str(

python的urllib模块显示下载进度示例_python

复制代码 代码如下:  def report_hook(count, block_size, total_size):...     print '%02d%%'%(100.0 * count * block_size/ total_size)... urllib.urlretrieve("http://sports.sina.com.cn/", reporthook= report_hook)00%01%03%...

python代码制作configure文件示例_python

在lua中,一直用lua作为config文件,或承载数据的文件 - 好处是lua本身就很好阅读,然后无需额外写解析的代码,还支持在configure文件中读环境变量,条件判断等. 在lua中通过loadfile, setfenv实现) python: cat config.py bar = 10 foo=100 cat python_as_config.py: ns = {} execfile('config.py', ns) print "\n".join(sorted(dir(ns

python实现保存网页到本地示例_python

学习python示例:实现保存网页到本地 复制代码 代码如下: #coding=utf-8__auther__ = 'xianbao'import urllibimport osdef reporthook(blocks_read, block_size, total_size): if not blocks_read:  print '打开连接'  return if total_size < 0:  print "%d正在读取(%dbytes完成)"%(blocks_read