Getting user input within tqdm loops

自古美人都是妖i 提交于 2021-02-11 14:11:04

问题


I'm writing a script where a user has to provide input for each element of a large list. I'm trying to use tqdm to provide a progress bar for the user, but I can't find a good way to get input within the tqdm loop without breaking the output.

I'm aware of tqdm.write() for writing to the terminal during a tqdm loop, but is there a way of getting input?

For an example of what I'm trying to do, consider the code below:

from tqdm import tqdm
import sys
from time import sleep

def do_stuff(x): sleep(0.5)

stuff_list = ['Alpha', 'Beta', 'Gamma', 'Omega']

for thing in tqdm(stuff_list):
    input_string = input(thing + ": ")
    do_stuff(input_string)

If I run this code, I get the following output:

0%|                                                                                            | 0/4 [00:00<?, ?it/s]Alpha: A
 25%|█████████████████████                                                               | 1/4 [00:02<00:07,  2.54s/it]Beta: B
 50%|██████████████████████████████████████████                                          | 2/4 [00:03<00:04,  2.09s/it]Gamma: C
 75%|███████████████████████████████████████████████████████████████                     | 3/4 [00:04<00:01,  1.72s/it]Omega: D
100%|████████████████████████████████████████████████████████████████████████████████████| 4/4 [00:05<00:00,  1.56s/it]

I've tried using tqdm.external_write_mode, but this simply didn't display the progress bar whenever an input was waiting, which is not the behaviour I'm looking for.

Is there an easy way of doing this, or am I going to have to swap libraries?


回答1:


It isn't possible to display the progress bar while inside the input() function, because once a line is finished, it cannot be removed any more. It's a technical limitation of how command lines work. You can only remove the current line until you wrote a newline.

Therefore, I think the only solution is to remove the status bar, let the user input happen and then display it again.

from tqdm import tqdm
import sys
from time import sleep

def do_stuff(x): sleep(0.5)

stuff_list = ['Alpha', 'Beta', 'Gamma', 'Omega']

# To have more fine-control, you need to create a tqdm object
progress_iterator = tqdm(stuff_list)

for thing in progress_iterator:
    # Remove progress bar
    progress_iterator.clear()

    # User input
    input_string = input(thing + ": ")

    # Write the progress bar again
    progress_iterator.refresh()

    # Do stuff
    do_stuff(input_string)

If you don't like the fact that the progress_iterator object exists after the loop, use the with syntax:

with tqdm(stuff_list) as progress_iterator:
    for thing in progress_iterator:
        ...

EDIT: If you are willed to sacrifice platform independence, you can freely move the cursor and delete lines with this:

from tqdm import tqdm
import sys
from time import sleep

def do_stuff(x): sleep(0.5)

stuff_list = ['Alpha', 'Beta', 'Gamma', 'Omega']

# Special console commands
CURSOR_UP_ONE = '\x1b[1A'

# To have more fine-control, you need to create a tqdm object
progress_iterator = tqdm(stuff_list)

for thing in progress_iterator:

    # Move the status bar one down
    progress_iterator.clear()
    print(file=sys.stderr)
    progress_iterator.refresh()

    # Move the cursor back up
    sys.stderr.write('\r')
    sys.stderr.write(CURSOR_UP_ONE)

    # User input
    input_string = input(thing + ": ")

    # Refresh the progress bar, to move the cursor back to where it should be.
    # This step can be omitted.
    progress_iterator.refresh()

    # Do stuff
    do_stuff(input_string)

I think this is the closest you will get to tqdm.write(). Note that the behaviour of input() can never be identical to tqdm.write(), because tqdm.write() first deletes the bar, then writes the message, and then writes the bar again. If you want to display the bar while being in input(), you have to do some platform-dependent stuff like this.



来源:https://stackoverflow.com/questions/56791800/getting-user-input-within-tqdm-loops

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!