I wrote a Python script to download files using multiple (source) IP addresses -- kindly suggest any improvements.import cgiimport osimport posixpathimport Queueimport threadingimport urllibimport urlparseimport randomimport reimport shutilimport timeimport requestsimport requests_toolbeltdef get_IPs():    Returns all available IP addresses in a list.    # TODO: Windows only. Other options?    out = []    for i in os.popen('ipconfig'):        i = i.strip()        if i.startswith('IP'):            out.append(i.rsplit(' ', 1)[-1])    return outdef get_info(url):    Returns name and size of file to be downloaded.    try:        resp = requests.head(url, allow_redirects=True)        name = cgi.parse_header(resp.headers['content-disposition'])[1]['filename']    except KeyError:        path = urlparse.urlsplit(url).path        name = posixpath.basename(path)    name = urllib.unquote_plus(name)    size = int(resp.headers['content-length'])    return name, sizedef worker(url, session, ud, part, size):    Downloads a part of the file specified by 'part' parameter.    # TODO: optimal tries, timeout?    for _ in xrange(2):        try:            open('%s/%04d' % (ud, part), 'wb').write(                session.get(url, timeout=(2, 7), headers={'range': 'bytes=%s-%s' % (                    part*chunk, min(size, part*chunk + chunk - 1))}).content)            break        except:            pass    else:        worker(url, sessions_queue.get(), ud, part, size)    sessions_queue.put(session)def summary(name, size, elapsed):    Prints summary of the download after it is completed.    print (        '--\n'        '%s download completed.\n'        'Time elapsed: %.2fs\n'        'Average download speed: %.2f MB/s\n'        '--' % (name, elapsed, size/elapsed/2**20))def download(url):    Downloads the file pointed to by 'url' parameter.    start = time.clock()    name, size = get_info(url)    # random id of length 20    ud = '%0x' % random.getrandbits(80)    os.mkdir(ud)    threads = []    for i in xrange(size/chunk + (size%chunk != 0)):        t = threading.Thread(target=worker, args=(url, sessions_queue.get(), ud, i, size))        threads.append(t)        t.start()    # characters \/:*?<>| not allowed in filenames in Windows    name = re.sub(r'[\\/:*?<>|]', '_', name)    # TODO: check if a file is already present with same name    out = open(name, 'ab')    for i, t in enumerate(threads):        t.join()        out.write(open('%s/%04d' % (ud, i), 'rb').read())    summary(name, size, time.clock() - start)    shutil.rmtree(ud)def main():    IPs = get_IPs()    print len(IPs), 'IPs available.'    for ip in IPs:        adapter = requests_toolbelt.adapters.SourceAddressAdapter(ip)        session = requests.Session()        session.mount('http://', adapter)        session.mount('https://', adapter)        sessions_queue.put(session)    while True:        threading.Thread(target=download, args=(raw_input(),)).start()if __name__ == '__main__':    sessions_queue = Queue.Queue()    KB = 1024    MB = 1024*KB    # TODO: optimal size?    chunk = 100*KB    main()I am using it with about 100 IP addresses on my Ethernet -- each with about 100 KB/s speed. What'd be optimal configuration? (numbers of threads, chunk size)
Downloading files using Python-requests
python;multithreading;python 2.7