Display State

At the moment we are able to download a file. But we have no information on how fast our download is and if it is completed or there is some error.

Before we start, here is the tiny program we made previously if you need to refresh your mind:

import bitpit

#will download this
url = 'https://www.python.org/static/img/python-logo.png'

#this is our downloader
dl = bitpit.Downloader(url)

#start downloading and tell user download has started.
dl.start()
print('Download has started.')

#end of the main thread

Now it is time to make it better.

Display the file size

If we are downloading a file, we probably want to know the file size. bitpit is written in an event driven style. It is a little similar to GTK library if you have used it before. We need to do 2 steps to show the file size. First, we need to define a function that will be called when the file size is known:

def on_size_changed(downloader):
    print(downloader.size)

This function takes 1 argument: downloader which is the Downloader instance that we just knew its file size. In the function, we print the Downloader.size property, which is just the file size in bytes.

Next, we need to tell the downloader to call this function as soon as it knows the file size. You probably want to do this just before you start the download. This is done using Downloader.listen() method:

dl.listen('size-changed', on_size_changed)

The Downloader.listen() takes 2 arguments. The first is the signal to listen to. Here we listened to the size-changed signal which is emitted whenever the downloader gets to know the size of the file being downloaded. The second argument is the function to call when the signal is emitted. Here we put the function we defined above.

After this call to Downloader.listen(), our function will be called as soon as the file size is known. Our full program now becomes as follows:

import bitpit

def on_size_changed(downloader):
    print('The file size is', downloader.size)

#will download this
url = 'https://www.python.org/static/img/python-logo.png'

#this is our downloader
dl = bitpit.Downloader(url)

#listen to signals
#print size as soon as it is known
dl.listen('size-changed', on_size_changed)

#start downloading and tell user download has started.
dl.start()
print('Download has started.')

#end of the main thread

If you notice, the size is expressed in bytes. Showing the size in bytes gives us a very big number that is difficult for humans to read. It would be easier for us if we could display the size in Kilobytes or Megabytes. This can be done by modifying the callback function on_size_changed() to be as follows:

def on_size_changed(downloader):
    print('The file size is', *downloader.human_size)

We just replaced Downloader.size property with Downloader.human_size property. Downloader.human_size property gives us a 2-element tuple. The first element is a float representing the size and the second element is a string suffix with the value KB for kilobytes or MB for megabytes and so on. In our call to print() function, we unpacked the tuple arguments using python *-operator. If you are not familiar with this, check it out in the python here.

When I tried the new callback function, I got the following message printed:

The file size is 9.865234375 KB

We can use python string formatting to make it look better but we will leave it for later.

First, we need to import the library:

import bitpit

Now let’s specify the URL we are going to download. We are going to download python logo:

url = 'https://www.python.org/static/img/python-logo.png'

Next comes bitpit business. We create a Downloader instance:

dl = bitpit.Downloader(url)

Finally we start the download:

dl.start()
print('Download has started.')

Now the download will start. Notice that Downloader.start() call will not block. The message Download has started. will be printed immediately before the download finishes. Then our main thread will end but the downloading thread will keep running until the file is fully downloaded or an error occures.

If you try the example above, you will see Download has started message printed on the screen and nothing else. The program will freeze until the download finishes. Imagine if we have a very big file such as linux mint. It will take a long time without us knowing how much we have downloaded. That is not so convenient isn’t it? We will look at that later but for now, let’s look at the program we have written so far:

import bitpit

#will download this
url = 'https://www.python.org/static/img/python-logo.png'

#this is our downloader
dl = bitpit.Downloader(url)

#start downloading and tell user download has started.
dl.start()
print('Download has started.')

#end of the main thread

Next, we will make the program give us information about the download such as whether it has started or faced an error and also the download speed.