ZZZ
ZZZ

Reputation: 3

How to display mb/s instead of b/s in progressbar and Python?

I am trying to change the way progressbar (version 2) displays the transferred/total file size in Python 3. Here's the code:

import progressbar
import requests

url = 'http://download.openbricks.org/sample/H264/big_buck_bunny_1080p_H264_AAC_25fps_7200K_short.MP4'

request = requests.get(url, stream=True)

file         = open('test.mp4', 'wb')
file_size    = int(request.headers['Content-Length'])
file_size_mb = round(file_size / 1024 / 1024,2)

chunk_sz = 512

widgets = [progressbar.Bar(marker="#",left="[",right="]"),
           progressbar.Percentage()," | ",
           progressbar.FileTransferSpeed()," | ",
           progressbar.SimpleProgress()," | ",
           progressbar.ETA()]

bar = progressbar.ProgressBar(widgets=widgets, maxval=file_size).start()

i = 0

for chunk in request.iter_content(chunk_size=chunk_sz):
    file.write(chunk)
    i += len(chunk)
    bar.update(i)

bar.finish()
print('File size: {0} MB'.format(file_size_mb))

file.close()

The output:

[#########################] 91% | 741.3 KiB/s | 3397632 of 3714474 | Time: 00:00:08

File size: 3.54 MB

I want to be able to make the "3397632 of 3714474" be displayed in the MB format (like in the file_size_mb variable), not in Bytes as it is being displayed by progressbar by default.

I've read the docs in Progress Bar’s documentation but I couldn't find the answer to my question in any of the examples given there.

Upvotes: 0

Views: 798

Answers (2)

Tryph
Tryph

Reputation: 6219

you can obtain this kind of display relatively easily with DataSize widget:

[######                                 ] 17% | 256.0 KiB/s | 631.0 KiB /   3.5 MiB | ETA: 0:00:11

you can do this by replacing the SimpleProgress widgets by two DataSize widgets, as shown below:

widgets = [progressbar.Bar(marker="#",left="[",right="]"),
           progressbar.Percentage(), " | ",
           progressbar.FileTransferSpeed(), " | ",
           progressbar.DataSize(), " / ",
           progressbar.DataSize(variable="max_value"), " | ",
           progressbar.ETA()]

By default, the DataSize widget displays the current value, but you can specify that you want it to display the max value by passing it "max_value" as variable parameter.

The problem is that it is not documented and you have to inspect the code to find this information. So this could be changed one day and no more work with a later version of the module.

Considering the DataSize doc, it seems you can alter the default format by passing a custom value to format parameter. The default format is

format='%(scaled)5.1f %(prefix)s%(unit)s'

I think you could get two decimal numbers by specifying this format:

format='%(scaled)5.2f %(prefix)s%(unit)s'

Concerning the displayed unit, the doc mentions the prefixes parameter which defaults to

prefixes=('', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi')

You could probably pass another tuple with the prefixes you want. But consider this article discussing about binary prefixes before doing that. If you use powers of 1024 to convert your units, and if you want to be exact, then you probably wants to use the IEC binary prefixes with the "i" character.


An other, but longer, way to achieve what you want would be to derive the SimpleProgress class to make one which fits you needs.

Upvotes: 1

Loïc
Loïc

Reputation: 11942

From progressbar documentation :

class progressbar.widgets.SimpleProgress(format=’%(value)d of %(max_value)d’,
max_width=None, **kwargs)

Bases: progressbar.widgets.FormatWidgetMixin, progressbar.widgets.WidgetBase

Returns progress as a count of the total (e.g.: “5 of 47”)

So I'd assume you can use the format parameter to do what you need.

widgets = [progressbar.Bar(marker="#",left="[",right="]"),
           progressbar.Percentage()," | ",
           progressbar.FileTransferSpeed()," | ",
           progressbar.SimpleProgress(format='%(value/1024/1024)d of %(max_value/1024/1024)d')," | ",
           progressbar.ETA()]

Another way would consist in getting getting the output from simpleProgress, parse it to get the values, and do the maths manually.

Upvotes: 0

Related Questions