Python多线程下载器,文件下载正确,但是无法再Windows上运行
本文介绍了Python多线程下载器,文件下载正确,但是无法再Windows上运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
问 题
一. 描述问题&上下文环境
想下载QQ.exe到Windows电脑
用了多线程
文件下载正确(大小), 但是为"无效的exe文件"
debug了很久, 没有找到原因
Windows7_64-py2.7.11
Python 2.7.11 |Anaconda 2.5.0 (64-bit)| (default, Jan 29 2016, 14:26:21) [MSC v
1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://anaconda.org
[Anaconda2] C:\Users\hzm>pip show requests
---
Metadata-Version: 1.1
Name: requests
Version: 2.9.1
Summary: Python HTTP for Humans.
Home-page: http://python-requests.org
Author: Kenneth Reitz
Author-email: me@kennethreitz.com
License: Apache 2.0
Location: c:\anaconda2\lib\site-packages
Requires:
重现: 拷贝以下代码, 并且运行即可
二. 相关代码&重现
from __future__ import absolute_import, unicode_literals
import requests
import threading
class Downloader(object):
def __init__(self, url, thread_amount, filename, headers=None):
"""构造下载器
在开始下载前,准备好初始资源
:param url: 需要下载的url地址
:param thread_amount: 线程数量
:param filename: 本地存储文件名
:param headers: 可以适当添加合适的headers字段
:return:
"""
self._url = url
self._thread_amount = thread_amount
self.fd = open(filename, 'wb')
if headers is None:
self._headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Ge'
'cko) Chrome/50.0.2661.102 Safari/537.36'}
self._total = int(self.get_total(self._url) )
def start_download(self):
"""Start download the resource
步骤:
获取资源的长度(构造器中已经做好)
根据长度,线程数量切成一个一个范围(见split)
开始线程,分配各自任务下载
合并线程
:return:
"""
ranges = self.split()
thread_list = []
for i in range(self._thread_amount):
start, end = ranges[i] #获取一个范围
t = threading.Thread(target=self.download, args=(start, end))
t.start()
thread_list.append(t)
for t in thread_list: #合并每个线程, 有更好的方法,这里不知道如何做
t.join()
self.fd.close()
def get_total(self, url):
return requests.head(url).headers['Content-Length']
def split(self):
"""依据线程数量,将total进行切片
:return: 范围列表, 最后一个范围的end为空. 如 [(0, 10), (11, 20), (21, '') ]
"""
offset = int(self._total / self._thread_amount)
ranges = []
for i in range(self._thread_amount):
if i == self._thread_amount - 1:
ranges.append((i * offset, ''))
else:
ranges.append((i * offset, (i + 1) * offset))
return ranges
def download(self, start, end):
"""下载某一范围的数据,并写入文件
文件是一直打开的,写入的数据是二进制/文本
:param start: 开始点
:param end: 结束点
:return:
"""
self._headers['Range'] = 'Bytes=%s-%s' % (start, end)
self._headers['Accept-Encoding'] = '*'
response = requests.get(self._url, headers=self._headers)
self.fd.seek(start)
self.fd.write(response.content)
if __name__ == '__main__':
url = 'http://sw.bos.baidu.com/sw-search-sp/software/0fc9db1ea0b/QQ_8.3.18027.0_setup.exe'
thread_amount = 10
filename = 'qq-2.exe'
d = Downloader(url,
thread_amount,
filename)
d.start_download()
三. 报错信息
运行代码, 运行QQ.exe文件, 即可看到报错信息
四. 相关截图
五. 已经尝试哪些方法仍然没有解决(附上相关链接)
六.问题简化
解决方案
多线程操作self.fd要加锁
PS 文件大小不对啊 你用代码跑的文件大小和wget直接下载的文件大小差不少啊
这篇关于Python多线程下载器,文件下载正确,但是无法再Windows上运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文