d Completed:%.2f%%\n' % (size, downloadsize,100)
? ? ? ? ? ? else:
? ? ? ? ? ? ? ? show = '\nSize is not mathed!\n'
? ? ? ? ? ? ? ? flag=False
? ? ? ? else:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #单线程下载的后续处理
? ? ? ? ? ? show = '\nTotal Size: %d\n'% downloaded
? ? ? ? sys.stdout.write(show)
? ? ? ? sys.stdout.flush()
? ? ? ? if flag:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #确认下载的临时文件没问题后将各文件整合为最终的目标文件
? ? ? ? ? ? print('Integrating files...')
? ? ? ? ? ? num=1
? ? ? ? ? ? while os.path.exists(output):? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #防止与本地已存在文件重名
? ? ? ? ? ? ? ? fname,fext=os.path.splitext(output)
? ? ? ? ? ? ? ? if '('+str(num-1)+')'+fext in output:
? ? ? ? ? ? ? ? ? ? output = output.replace('('+str(num-1)+')'+fext,'('+str(num)+')'+fext)
? ? ? ? ? ? ? ? else:
? ? ? ? ? ? ? ? ? ? fname += '('+str(num)+')'
? ? ? ? ? ? ? ? ? ? output = fname+fext
? ? ? ? ? ? ? ? num +=1
? ? ? ? ? ? if len(filename) ==1 :? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #单线程下载的话,直接将下载的文件重命名为目标文件即可
? ? ? ? ? ? ? ? os.rename(filename[0], output)
? ? ? ? ? ? else:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #多线程临时文件整合
? ? ? ? ? ? ? ? filehandle = open( output, 'wb+' )
? ? ? ? ? ? ? ? for i in filename:
? ? ? ? ? ? ? ? ? ? try:
? ? ? ? ? ? ? ? ? ? ? ? f = open( i, 'rb' )
? ? ? ? ? ? ? ? ? ? ? ? filehandle.write( f.read() )
? ? ? ? ? ? ? ? ? ? ? ? f.close()
? ? ? ? ? ? ? ? ? ? ? ? os.remove(i)
? ? ? ? ? ? ? ? ? ? except Exception as ex:
? ? ? ? ? ? ? ? ? ? ? ? print(ex)
? ? ? ? ? ? ? ? filehandle.close()
? ? ? ? ? ? if os.path.exists(output):
? ? ? ? ? ? ? ? print('Download Complete!')
? ? ? ? ? ? else:
? ? ? ? ? ? ? ? print('Failed to generate target file!')
? ? ? ? ? ? ? ? try:
? ? ? ? ? ? ? ? ? ? #os.remove(output)
? ? ? ? ? ? ? ? ? ? pass
? ? ? ? ? ? ? ? except:
? ? ? ? ? ? ? ? ? ? pass
? ? ? ? else:
? ? ? ? ? ? for i in filename:
? ? ? ? ? ? ? ? try:
? ? ? ? ? ? ? ? ? ? os.remove(i)
? ? ? ? ? ? ? ? ? ? pass
? ? ? ? ? ? ? ? except:
? ? ? ? ? ? ? ? ? ? pass
? ? ? ? ? ? print('Download Failed!')
? ? ? ? ? ? pass
? ? ? ? print('Consuming: {}\n'.format(consuming))? ? ? ? ? ? ? ? ? ? ? ? #输出耗时
else:
print('Failed to retrieve resource information!')
sys.exit()
def main(argv):? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #处理传入参数,使用了getopt模块,另外有一个更强大的处理传入参数的模块optparse
? ? try:
? ? ? ? options,args=getopt.getopt(argv,'hu:f:n:p:',['help','url=','target=','num=','proxy='])
? ? except Exception as ex:
? ? ? ? print(ex)
? ? ? ? sys.exit()
? ? num = 2
? ? url,target,proxies= '','',''
? ? url = 'http://www.pygtk.org/dist/pygtk2-tut.pdf'
? ? target = '/home/maple/Desktop'
? ? #proxies = 'http://127.0.0.1:8087'
? ? #proxies={}
? ? for name, value in options:
? ? ? ? if name in ('-h','--help'):
? ? ? ? ? ? print('No Help ^^')
? ? ? ? ? ? sys.exit()
? ? ? ? if name in ('-u','--url'):
? ? ? ? ? ? url = value
? ? ? ? if name in ('-t','--target'):
? ? ? ? ? ? target = value
? ? ? ? if name in ('-n','--num'):
? ? ? ? ? ? num = int(value)
? ? ? ? if name in ('-p','--proxy'):
? ? ? ? ? ? proxies=value
? ? #check args
? ? download(url,target,num,proxies)
if __name__ == '__main__':
? ? main(sys.argv[1:])
这段代码在异常处理方面写得有些乱,没怎么关心异常处理,需要时再改吧
另外多线程下载时,如果使用了代理,会导致下载到的文件与服务器提供的文件大小不符。从而下载失败。我使用的是GoAgent,代理服务器会自动对目标文件进行多线程下载,无视程序指定的下载字节范围。第一个线程就会下载到完整的文件,其他线程会下载冗余内容。没有找到规范的处理办法。变通的处理办法有2种:
1、将使用了代理的多线程下载强制指定为单线程下载
2、不进行文件大小的校验,将多线程下载的0号临时文件重命名为目标文件,其他临时文件删除。
两种方法实现都很简单,但是破坏代码的整体逻辑。没有加入代码中。运行截图:

下面关于Python的文章您也可能喜欢,不妨看看: