How to keep tqdm progress bar on the bottom of the terminal?

45 Views Asked by At

Here is the code

def download_from_dict(path_link_dict, folder)
    counter = 0
    for path, link, name in tqdm(path_link_dict):

        counter = counter + 1
        if os.path.isfile(folder + path + name):
            print('[ Already there! ] ' + name)
            continue

        if not os.path.isdir(folder + path):
            os.makedirs(folder + path)

        response = requests.get(link, headers=HEADERS)
        with open(folder + path + name, 'wb') as file:
            file.write(response.content)
        print('[*] Downloaded ' + name)

output is

progress bar..
[*] Downloaded something..
Progress bar..
[*] Downloaded something

desired output( I want the bar to stay on the bottom of the terminal. )

[*] Downloaded something
[*] Downloaded something
[*] Downloaded something
progress bar..

I have tried using the leave=False, position=0, and barfmt.. parameters for the tqdm function, but it didn't work I also have tried using \r before [*] Downloaded, but the bar is longer than the printed statement so it clears only a part of it. I have gone to the tqdm docs, and i couldn't solve this problem can you help?

2

There are 2 best solutions below

1
Wilson Salgado On

it is not an easy and straightforward solution in here, but there are interesting discussions and solutions on how to do that on a couple of previous questions here in stackoverflow: Redirect print command in python script through tqdm.write() and python progress bar using tqdm not staying on a single line

It is also going to depend if you require it in the standard terminal or jupyter notebook or another output...

0
aviso On

You can try the using tqdm.write() instead of print(), but I suggest instead of adapting your code to fit the library, use a library specifically designed for your use case. The library for this is Enlighten

You'd replace the above code with (contents of the for loop are unchanged):

import enlighten

MANAGER = enlighten.get_manager()

def download_from_dict(path_link_dict, folder)

    pbar = MANAGER.counter(total=len(path_link_dict), desc='Downloading', unit='files')

    for path, link, name in pbar(path_link_dict):

        if os.path.isfile(folder + path + name):
            print('[ Already there! ] ' + name)
            continue

        if not os.path.isdir(folder + path):
            os.makedirs(folder + path)

        response = requests.get(link, headers=HEADERS)
        with open(folder + path + name, 'wb') as file:
            file.write(response.content)
        print('[*] Downloaded ' + name)

You can find more information and options for customization in the documentation.

Also take a look at pathlib to simplify your file operations.