5

I am trying to make a simple function to download file in python The code is something like

def download(url , dest):
    urllib.urlretrieve(url, dest)

My issue is that if I want to cancel the download process in the middle of downloading how do I approach???

This function runs in the background of app and is triggered by a button. Now I am trying to trigger it off with another button.

The platform is XBMC.

Abul Hasnat
  • 1,541
  • 2
  • 16
  • 23
  • 1
    I think you have to give us a litte bit more to go on. How are you calling that function, are you using a browser to do this, or are you executing it via shell? – Henrik Andersson Mar 01 '13 at 13:48
  • 2
    @limelights How would you run Python code in a browser? – unwind Mar 01 '13 at 13:48
  • @unwind well, clearly he is lacking in explaining this problem and so I believe he has the probable chance of being in Django or Flask or Bottle and then calling this function. I was just trying to get the ball rolling on explanation. Also, he might be trolling around in skulpt :P – Henrik Andersson Mar 01 '13 at 13:50
  • 3
    You can simply cancel the program itself, by hitting `CTRL+C` on your keyboard; but if you want something more complicated than that you need to provide more details on how you are running the code. – Burhan Khalid Mar 01 '13 at 13:50
  • I am running the app inside xbmc – Abul Hasnat Mar 01 '13 at 13:52

2 Answers2

3

A simple class to do the same as your download function:

import urllib
import threading

class Downloader:

    def __init__(self):
        self.stop_down = False
        self.thread = None

    def download(self, url, destination):
        self.thread = threading.Thread(target=self.__down, args=(url, destination))
        self.thread.start()

    def __down(self, url, dest):
        _continue = True
        handler = urllib.urlopen(url)
        self.fp = open(dest, "w")
        while not self.stop_down and _continue:
            data = handler.read(4096)
            self.fp.write(data)
            _continue = data
        handler.close()
        self.fp.close()

    def cancel(self):
        self.stop_down = True

So, when someone clicks the "Cancel" button you have to call the cancel() method.

Please note that this will not remove the partially downloaded file if you cancel it, but that should not be hard to achieve using os.unlink(), for example.

The following example script shows how to use it, starting the download of a ~20Mb file and cancelling it after 5 seconds:

import time
if __name__ == "__main__":
    url = "http://ftp.postgresql.org/pub/source/v9.2.3/postgresql-9.2.3.tar.gz"
    down = Downloader()
    down.download(url, "file")
    print "Download started..."
    time.sleep(5)
    down.cancel()
    print "Download canceled"
Salem
  • 12,808
  • 4
  • 34
  • 54
0

If you are canceling by pressing CTRL+C, then you can use this built in exception and proceed with what you think the best move should be.

In this case, if I cancel in the middle of a download, I simply want that partial file to be deleted:

def download(url , dest):
    try:
        urllib.urlretrieve(url, dest)
    except KeyboardInterrupt:
        if os.path.exists(dest):
            os.remove(dest)
    except Exception, e:
        raise
Kartik
  • 9,463
  • 9
  • 48
  • 52