python多線程http下載實(shí)現(xiàn)示例
測試平臺(tái) Ubuntu 13.04 X86_64 Python 2.7.4
花了將近兩個(gè)小時(shí), 問題主要?jiǎng)傞_始沒有想到傳一個(gè)文件對(duì)象到線程里面去, 導(dǎo)致下載下來的文件和源文件MD5不一樣,浪費(fèi)不少時(shí)間.
有興趣的同學(xué)可以拿去加上參數(shù),改進(jìn)下, 也可以加上斷點(diǎn)續(xù)傳.
# -*- coding: utf-8 -*-
# Author: ToughGuy
# Email: wj0630@gmail.com
# 寫這玩意兒是為了初步了解下python的多線程機(jī)制
# 平時(shí)沒寫注釋的習(xí)慣, 這次花時(shí)間在代碼里面寫上注釋也是希望有問題的地方請(qǐng)各位指正, 因?yàn)榭赡芪易约阂矝]弄明白.
# 測試平臺(tái) 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)設(shè)置下載數(shù)據(jù)的范圍
req.headers['Range'] = 'bytes=%s-%s' % (self.start_size, self.end_size)
f = urllib2.urlopen(req)
# 初始化當(dāng)前線程文件對(duì)象偏移量
offset = self.start_size
while 1:
block = f.read(self.buffer)
# 當(dāng)前線程數(shù)據(jù)獲取完畢后則退出
if not block:
with lock:
print '%s done.' % self.getName()
break
# 寫如數(shù)據(jù)的時(shí)候當(dāng)然要鎖住線程
# 使用 with lock 替代傳統(tǒng)的 lock.acquire().....lock.release()
# 需要python >= 2.5
with lock:
sys.stdout.write('%s saveing block...' % self.getName())
# 設(shè)置文件對(duì)象偏移地址
self.fobj.seek(offset)
# 寫入獲取到的數(shù)據(jù)
self.fobj.write(block)
offset = offset + len(block)
sys.stdout.write('done.\n')
def main(url, thread=3, save_file='', buffer=1024):
# 最大線程數(shù)量不能超過max_thread
thread = thread if thread <= max_thread else max_thread
# 獲取文件的大小
req = urllib2.urlopen(url)
size = int(req.info().getheaders('Content-Length')[0])
# 初始化文件對(duì)象
fobj = open(save_file, 'wb')
# 根據(jù)線程數(shù)量計(jì)算 每個(gè)線程負(fù)責(zé)的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:
# 最后一個(gè)線程加上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()
# 等待所有線程結(jié)束
for t in plist:
t.join()
# 結(jié)束當(dāng)然記得關(guān)閉文件對(duì)象
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并發(fā)編程之多進(jìn)程、多線程、異步和協(xié)程詳解
- Python控制多進(jìn)程與多線程并發(fā)數(shù)總結(jié)
- Python 多進(jìn)程并發(fā)操作中進(jìn)程池Pool的實(shí)例
- Python多進(jìn)程并發(fā)(multiprocessing)用法實(shí)例詳解
- python實(shí)現(xiàn)多線程的方式及多條命令并發(fā)執(zhí)行
- 詳解Python中的多線程編程
- Python中多線程thread與threading的實(shí)現(xiàn)方法
- 淺析Python中的多進(jìn)程與多線程的使用
- 基python實(shí)現(xiàn)多線程網(wǎng)頁爬蟲
- Python多進(jìn)程并發(fā)與多線程并發(fā)編程實(shí)例總結(jié)
相關(guān)文章
python中使用pymssql庫操作MSSQL數(shù)據(jù)庫
這篇文章主要給大家介紹了關(guān)于python中使用pymssql庫操作MSSQL數(shù)據(jù)庫的相關(guān)資料,最近在學(xué)習(xí)python,發(fā)現(xiàn)好像沒有對(duì)pymssql的詳細(xì)說明,于是乎把官方文檔學(xué)習(xí)一遍,重要部分做個(gè)歸檔,方便以后查閱,需要的朋友可以參考下2023-08-08深入理解Python虛擬機(jī)中描述器的實(shí)現(xiàn)原理
這篇文章主要給大家介紹一個(gè)我們?cè)谑褂妙惖臅r(shí)候經(jīng)常使用但是卻很少在意的黑科技——描述器的實(shí)現(xiàn)原理,文中的示例代碼講解詳細(xì),需要的可以參考一下2023-05-05python list 查詢是否存在并且并返回下標(biāo)的操作
這篇文章主要介紹了python list 查詢是否存在并且并返回下標(biāo)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-05-05pytorch加載預(yù)訓(xùn)練模型與自己模型不匹配的解決方案
這篇文章主要介紹了pytorch加載預(yù)訓(xùn)練模型與自己模型不匹配的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-05-05使用python數(shù)據(jù)清洗代碼實(shí)例
這篇文章主要介紹了使用python數(shù)據(jù)清洗代碼實(shí)例,分享一下近期用python做數(shù)據(jù)清洗匯總的相關(guān)代碼,這里我們用到的python包有pandas、numpy、os等,需要的朋友可以參考下2023-07-07Python從使用線程到使用async/await的深入講解
Python在3.5版本中引入了關(guān)于協(xié)程的語法糖async和await,所以下面這篇文章主要給大家介紹了關(guān)于Python從使用線程到使用async/await的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-09-09python實(shí)現(xiàn)TCP服務(wù)器端與客戶端的方法詳解
這篇文章主要介紹了python實(shí)現(xiàn)TCP服務(wù)器端與客戶端的方法,以實(shí)例形式詳解分析了Python實(shí)現(xiàn)服務(wù)器端與客戶端的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04