在 Python 中替换控制台输出
- 2025-01-07 08:44:00
- admin 原创
- 94
问题描述:
我想知道如何在 Python 中创建一个漂亮的控制台计数器,就像在某些 C/C++ 程序中一样。
我有一个循环在做事,当前的输出如下:
Doing thing 0
Doing thing 1
Doing thing 2
...
更简洁的做法是只更新最后一行;
X things done.
我在许多控制台程序中都看到过这种情况,并且想知道是否/如何在 Python 中做到这一点。
解决方案 1:
一个简单的解决方案就是在字符串前写入`"
"`而不添加换行符;如果字符串永远不会变短,这就足够了......
sys.stdout.write("
Doing thing %i" % i)
sys.stdout.flush()
稍微复杂一点的是进度条……这是我正在使用的东西:
def start_progress(title):
global progress_x
sys.stdout.write(title + ": [" + "-"*40 + "]" + chr(8)*41)
sys.stdout.flush()
progress_x = 0
def progress(x):
global progress_x
x = int(x * 40 // 100)
sys.stdout.write("#" * (x - progress_x))
sys.stdout.flush()
progress_x = x
def end_progress():
sys.stdout.write("#" * (40 - progress_x) + "]
")
sys.stdout.flush()
你调用start_progress
传递操作的描述,那么百分比在progress(x)
哪里,最后x
`end_progress()`
解决方案 2:
更优雅的解决方案可能是:
def progress_bar(current, total, bar_length=20):
fraction = current / total
arrow = int(fraction * bar_length - 1) * '-' + '>'
padding = int(bar_length - len(arrow)) * ' '
ending = '
' if current == total else '
'
print(f'Progress: [{arrow}{padding}] {int(fraction*100)}%', end=ending)
current
使用和调用此函数total
:
progress_bar(69, 100)
结果应该是
Progress: [-------------> ] 69%
笔记:
对于Python 3.6 及以下版本
对于Python 2.x。
解决方案 3:
在python 3中,您可以这样做在同一行打印:
`print('', end='
')`
对于跟踪最新更新和进度特别有用。
如果想要查看循环的进度,我也会推荐 tqdm。它会将当前迭代和总迭代次数打印为进度条,并显示预计完成时间。超级有用且快捷。适用于 python2 和python3。
解决方案 4:
这是我不久前写的,真的很满意。请随意使用。
它需要一个index
andtotal
和可选的title
or bar_length
。完成后,用复选标记替换沙漏。
⏳ Calculating: [████░░░░░░░░░░░░░░░░░░░░░] 18.0% done
✅ Calculating: [█████████████████████████] 100.0% done
我提供了一个可以运行来测试它的示例。
import sys
import time
def print_percent_done(index, total, bar_len=50, title='Please wait'):
'''
index is expected to be 0 based index.
0 <= index < total
'''
percent_done = (index+1)/total*100
percent_done = round(percent_done, 1)
done = round(percent_done/(100/bar_len))
togo = bar_len-done
done_str = '█'*int(done)
togo_str = '░'*int(togo)
print(f' ⏳{title}: [{done_str}{togo_str}] {percent_done}% done', end='
')
if round(percent_done) == 100:
print(' ✅')
r = 50
for i in range(r):
print_percent_done(i,r)
time.sleep(.02)
shutil.get_terminal_size()
如果您感兴趣的话,我还有一个带有响应进度条的版本,具体取决于终端宽度。
解决方案 5:
print()
如果我们看一下函数,就可以不使用 sys 库来完成
print(*objects, sep=' ', end='
', file=sys.stdout, flush=False)
这是我的代码:
def update(n):
for i in range(n):
print("i:",i,sep='',end="
",flush=True)
time.sleep(1)
解决方案 6:
对于几年后偶然发现这一点的人(就像我一样),我稍微调整了 6502 的方法,使进度条可以减少也可以增加。在更多情况下很有用。感谢 6502 提供的出色工具!
基本上,唯一的区别是每次调用 progress(x) 时都会写入整行 #s 和 -s,并且光标始终返回到条形图的开头。
def startprogress(title):
"""Creates a progress bar 40 chars long on the console
and moves cursor back to beginning with BS character"""
global progress_x
sys.stdout.write(title + ": [" + "-" * 40 + "]" + chr(8) * 41)
sys.stdout.flush()
progress_x = 0
def progress(x):
"""Sets progress bar to a certain percentage x.
Progress is given as whole percentage, i.e. 50% done
is given by x = 50"""
global progress_x
x = int(x * 40 // 100)
sys.stdout.write("#" * x + "-" * (40 - x) + "]" + chr(8) * 41)
sys.stdout.flush()
progress_x = x
def endprogress():
"""End of progress bar;
Write full bar, then move to next line"""
sys.stdout.write("#" * 40 + "]
")
sys.stdout.flush()
解决方案 7:
另一个答案可能更好,但这就是我所做的。首先,我创建了一个名为progress的函数,它打印出退格字符:
def progress(x):
out = '%s things done' % x # The output
bs = '' * 1000 # The backspace
print bs,
print out,
然后我在主函数中循环调用它,如下所示:
def main():
for x in range(20):
progress(x)
return
这当然会删除整行,但你可以随意修改它,以达到你想要的效果。我最终用这种方法制作了一个进度条。
解决方案 8:
如果我理解得好(不确定)您想使用<CR>
而不是打印<LR>
?
如果是这样,这是可能的,只要控制台终端允许这样做(当输出 si 重定向到文件时它就会中断)。
from __future__ import print_function
print("count x
", file=sys.stdout, end=" ")
解决方案 9:
为Aravind Voggu的示例添加了更多功能:
def progressBar(name, value, endvalue, bar_length = 50, width = 20):
percent = float(value) / endvalue
arrow = '-' * int(round(percent*bar_length) - 1) + '>'
spaces = ' ' * (bar_length - len(arrow))
sys.stdout.write("
{0: <{1}} : [{2}]{3}%".format(\n name, width, arrow + spaces, int(round(percent*100))))
sys.stdout.flush()
if value == endvalue:
sys.stdout.write('
')
现在您可以生成多个进度条,而无需替换前一个进度条。
我还添加了name
一个具有固定宽度的值。
对于两次循环和两次的
progressBar()
结果的使用将如下所示:
解决方案 10:
from time import sleep
max_val = 40
for done in range(max_val):
sleep(0.05)
undone = max_val - 1 - done
proc = (100 * done) // (max_val - 1)
print(f"
Progress: [{('#' * done) + ('_' * undone)}] ({proc}%)", end='
')
print("
Done!")
Progress: [###################_____________________] (47%)
Progress: [########################################] (100%)
Done!
解决方案 11:
遇到了同样的问题并尝试了很多解决方案。
import sys
sys.stdout.write('
Blablabla')
非常有效!
解决方案 12:
下面的代码将每 0.3 秒计数从 0 到 137 的消息,替换之前的数字。
送至后台的符号数=数字数。
stream = sys.stdout
for i in range(137):
stream.write('' * (len(str(i)) + 10))
stream.write("Message : " + str(i))
stream.flush()
time.sleep(0.3)