Python简单多线程下载程序文件已损坏
这是我的第一篇文章。我做python编程已经有一段时间了,最近正在开发一个多线程下载程序。但问题是我的目标文件jpg被破坏了。也可以使用以下INF输入: 它显示了错误 使用输入时: 该文件已损坏 以下是代码:-Python简单多线程下载程序文件已损坏,python,multithreading,Python,Multithreading,这是我的第一篇文章。我做python编程已经有一段时间了,最近正在开发一个多线程下载程序。但问题是我的目标文件jpg被破坏了。也可以使用以下INF输入: 它显示了错误 使用输入时: 该文件已损坏 以下是代码:- import os, sys, requests import threading import urllib2 import time URL = sys.argv[1] def buildRange(value, numsplits): lst = [] for
import os, sys, requests
import threading
import urllib2
import time
URL = sys.argv[1]
def buildRange(value, numsplits):
lst = []
for i in range(numsplits):
if i == 0:
lst.append('%s-%s' % (i, int(round(1 + i * value/(numsplits*1.0) + value/(numsplits*1.0)-1, 0))))
else:
lst.append('%s-%s' % (int(round(1 + i * value/(numsplits*1.0),0)), int(round(1 + i * value/(numsplits*1.0) + value/(numsplits*1.0)-1, 0))))
return lst
def main(url=None, splitBy=5):
start_time = time.time()
if not url:
print "Please Enter some url to begin download."
return
fileName = "image.jpg"
sizeInBytes = requests.head(url, headers={'Accept-Encoding': 'identity'}).headers.get('content-length', None)
print "%s bytes to download." % sizeInBytes
if not sizeInBytes:
print "Size cannot be determined."
return
dataDict = {}
# split total num bytes into ranges
ranges = buildRange(int(sizeInBytes), splitBy)
def downloadChunk(idx, irange):
req = urllib2.Request(url)
req.headers['Range'] = 'bytes={}'.format(irange)
dataDict[idx] = urllib2.urlopen(req).read()
# create one downloading thread per chunk
downloaders = [
threading.Thread(
target=downloadChunk,
args=(idx, irange),
)
for idx,irange in enumerate(ranges)
]
# start threads, let run in parallel, wait for all to finish
for th in downloaders:
th.start()
for th in downloaders:
th.join()
print 'done: got {} chunks, total {} bytes'.format(
len(dataDict), sum( (
len(chunk) for chunk in dataDict.values()
) )
)
print "--- %s seconds ---" % str(time.time() - start_time)
if os.path.exists(fileName):
os.remove(fileName)
# reassemble file in correct order
with open(fileName, 'w') as fh:
for _idx,chunk in sorted(dataDict.iteritems()):
fh.write(chunk)
print "Finished Writing file %s" % fileName
print 'file size {} bytes'.format(os.path.getsize(fileName))
if __name__ == '__main__':
main(URL)
这里的缩进可能是错误的,所以这里的代码是pastebindotcom/wGEkp878
如果有人能指出错误,我将不胜感激
编辑:一个家伙建议的
def buildRange(value, numsplits):
lst = []
for i in range(numsplits):
first = i if i == 0 else buildRange().start(i, value, numsplits)
second = buildRange().end(i, value, numsplits)
lst.append("{}-{}".format(first, second))
return lst
有人能告诉我如何保存下载的零件文件,如零件1、零件2等。结果证明,文件必须以二进制模式打开,用“wb”而不是“w”。如果仅用“w”打开,将写入一堆额外的字符。这与derpy windows与linux新行语义有关。如果您使用“wb”,它将准确地将您输入的内容写入文件 编辑: 如果要存储单个文件部分,可以进行更改
# reassemble file in correct order
with open(fileName, 'w') as fh:
for _idx,chunk in sorted(dataDict.iteritems()):
fh.write(chunk)
print "Finished Writing file %s" % fileName
print 'file size {} bytes'.format(os.path.getsize(fileName))
到
作为第一个猜测,您拥有的buildRange函数看起来比它应该的更复杂,这也可能是您的问题。还有,很抱歉,这并不是对你问题的回答,但像这样的多线程下载几乎肯定比在单个请求中完成要花更多的时间。原因是,尽管您的所有数据都是同时下载的,但您的带宽仍然有限,现在您还有许多其他事情要做。这是一个很酷的实验,当然,绝对值得完成。你能告诉我如何存储作为第1部分、第2部分、第3部分和第4部分下载的部分文件吗?你原来的构建范围似乎可以工作,但新的构建范围做得更干净、更好。真正的问题似乎是增加了额外的新行字符!每当遇到“\n”时,都会在其前面插入一个额外的0x0D。如何解决该问题?另外,您能告诉我如何将下载的部件文件保存为第1部分第2部分ETC将无法下载正确的文件102331字节。完成:得到5个块,总共102331字节-1.9279999733秒-完成写入文件image.jpg文件大小102948字节我在您提到的几个文件上尝试过,它肯定会将正确的信息写入文件。从字面上说,你需要更改的是openfileName的行,将“w”改为“fh:to”,将“wb”改为“fh:thank”.你能告诉我如何保存零件文件吗
# reassemble file in correct order
for _idx,chunk in sorted(dataDict.iteritems()):
with open(fileName + str(".part-") + str(_idx), 'wb') as fh:
fh.write(chunk)
print "Finished Writing file %s" % fileName
#print 'file size {} bytes'.format(os.path.getsize(fileName))