【问题标题】:Asynchronous file downloads in PythonPython中的异步文件下载
【发布时间】:2013-09-18 23:24:34
【问题描述】:

我正在尝试找到一种在 Python(2.6) 中异步下载多个文件的方法,最好是通过请求模块。 Gevent 和 Twisted 也可以接受,因为我将在不久的将来学习它们。

我的应用程序需要在短时间内下载40+个文件,我想一次连续下载4个文件。每次一个文件下载完成时,都会启动另一个文件,因此它保持在 4。 这可能吗?

【问题讨论】:

    标签: python


    【解决方案1】:

    对于这样一个简单的任务,您不需要使用任何外部库或框架,将 url 列表放入队列中,启动 4 个线程,每个线程应从队列中获取一个项目并下载它。

    类似这样的:

    import sys
    import os
    import urllib
    import threading
    from Queue import Queue
    
    class DownloadThread(threading.Thread):
        def __init__(self, queue, destfolder):
            super(DownloadThread, self).__init__()
            self.queue = queue
            self.destfolder = destfolder
            self.daemon = True
    
        def run(self):
            while True:
                url = self.queue.get()
                try:
                    self.download_url(url)
                except Exception,e:
                    print "   Error: %s"%e
                self.queue.task_done()
    
        def download_url(self, url):
            # change it to a different way if you require
            name = url.split('/')[-1]
            dest = os.path.join(self.destfolder, name)
            print "[%s] Downloading %s -> %s"%(self.ident, url, dest)
            urllib.urlretrieve(url, dest)
    
    def download(urls, destfolder, numthreads=4):
        queue = Queue()
        for url in urls:
            queue.put(url)
    
        for i in range(numthreads):
            t = DownloadThread(queue, destfolder)
            t.start()
    
        queue.join()
    
    if __name__ == "__main__":
        download(sys.argv[1:], "/tmp")
    

    用法:

    $ python download.py http://en.wikipedia.org/wiki/1 http://en.wikipedia.org/wiki/2 http://en.wikipedia.org/wiki/3 http://en.wikipedia.org/wiki/4
    [4456497152] Downloading http://en.wikipedia.org/wiki/1 -> /tmp/1
    [4457033728] Downloading http://en.wikipedia.org/wiki/2 -> /tmp/2
    [4457701376] Downloading http://en.wikipedia.org/wiki/3 -> /tmp/3
    [4458258432] Downloading http://en.wikipedia.org/wiki/4 -> /tmp/4
    

    【讨论】:

    • 但这不是异步的,对吧?在文件下载之前,我们会阻塞线程。
    • @user2963977 在单独的线程中与主线程异步下载,在示例中我们无事可做,所以我们等待但您可以做其他事情,例如向用户显示统计数据或与他一起玩井字游戏直到文件下载
    • 等等,什么?使用 GIL,程序不会做任何其他事情,对吧?
    • @0xc0de GIL 并不意味着多线程不起作用,GIL 只影响计算而不阻塞 IO 调用
    猜你喜欢
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    • 1970-01-01
    • 1970-01-01
    • 2013-10-11
    相关资源
    最近更新 更多