我正在编写一个脚本,其中用户必须为大列表的每个元素提供输入。我正在尝试使用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
,但是只要有输入等待,它就不会显示进度条,这不是我要寻找的行为。
是否有一种简便的方法来执行此操作,或者我将不得不交换库?
答案 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()
中显示栏,则必须做一些与平台相关的操作,