1 # -*- coding: utf-8 -*-
3 from __future__
import with_statement
5 import threading
, Queue
, urllib2
9 class DownloadThread(threading
.Thread
):
11 """Thread object for downloading files.
13 Takes a url string and output file name as required parameters.
17 CONNECTING
, DOWNLOADING
, DONE
, ERROR
= range(4)
20 def __init__(self
, url
, fname
, chunk_size
=16384, timeout
=None):
21 threading
.Thread
.__init
__(self
)
22 self
.out_queue
= Queue
.Queue(0)
23 self
.in_queue
= Queue
.Queue(0)
26 self
.chunk_size
= chunk_size
27 self
.timeout
= timeout
31 with
open(self
.fname
, "wb") as ofile
:
33 self
.out_queue
.put((self
.CONNECTING
, 0))
34 if not (self
.timeout
is None):
35 resp
= urllib2
.urlopen(self
.url
, timeout
=self
.timeout
)
37 resp
= urllib2
.urlopen(self
.url
)
40 event
= self
.in_queue
.get(block
=False)
43 if event
== self
.ABORT
:
44 raise Exception("Aborted by parent thread")
45 self
.out_queue
.put((self
.DOWNLOADING
, progress
))
46 d
= resp
.read(self
.chunk_size
)
51 self
.out_queue
.put((self
.DONE
, progress
))
53 self
.out_queue
.put((self
.ERROR
, e
))
57 assert len(sys
.argv
) >= 2, "Please specify a URL to download."
58 assert len(sys
.argv
) >= 3, "Please specify a file name to save to."
59 dt
= DownloadThread(sys
.argv
[1], sys
.argv
[2], timeout
=5)
60 print "Starting thread..."
64 (status
, progress
) = dt
.out_queue
.get(block
=True)
65 if status
== dt
.CONNECTING
:
67 elif status
== dt
.DOWNLOADING
:
68 print "Downloading: %d bytes received" % progress
69 elif status
== dt
.DONE
:
71 elif status
== dt
.ERROR
:
72 # progress is an exception object
74 except KeyboardInterrupt, e
:
75 print "Keyboard interrupt received; aborting."
76 dt
.in_queue
.put(dt
.ABORT
)
78 print "Done! %d bytes received!" % progress
80 if __name__
== "__main__":