在tqdm循环中获取用户输入

时间:2019-06-27 13:11:26

标签: python-3.x tqdm

我正在编写一个脚本,其中用户必须为大列表的每个元素提供输入。我正在尝试使用tqdm为用户提供进度条,但是我找不到在不中断输出的情况下在tqdm循环中获取输入的好方法。

我知道tqdm.write()可以在tqdm循环中写入终端,但是有没有办法获取输入?

有关我要执行的操作的示例,请考虑以下代码:

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)

如果运行此代码,则会得到以下输出:

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]

我尝试使用tqdm.external_write_mode,但是只要有输入等待,它就不会显示进度条,这不是我要寻找的行为。

是否有一种简便的方法来执行此操作,或者我将不得不交换库?

1 个答案:

答案 0 :(得分:0)

在input()函数内部无法显示进度条,因为一旦一行结束,就无法再删除它。这是命令行工作方式的技术限制。您只能删除当前行,直到您写了换行符为止。

因此,我认为唯一的解决方案是删除状态栏,让用户输入发生,然后再次显示。

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)

如果您不喜欢在循环之后存在progress_iterator对象的事实,请使用with语法:

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

编辑: 如果您愿意牺牲平台独立性,则可以使用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)

我认为这是您最接近tqdm.write()的地方。请注意,input()的行为永远不会与tqdm.write()相同,因为tqdm.write()首先删除该栏,然后写入消息,然后再次写入该栏。如果您想在input()中显示栏,则必须做一些与平台相关的操作,