Python睡眠函数的倒计时显示

31

我在我的程序中使用了time.sleep(10)。在运行程序时,能否在shell中显示倒计时?

>>>run_my_program()
tasks done, now sleeping for 10 seconds

然后我希望它能做10、9、8、7...的倒计时。

这可能吗?


感谢您提供所有精彩的答案。 - user1681664
使用Tkinter、Gtk、Twisted或Asyncio事件循环进行倒计时。相关链接:https://dev59.com/4sKRzogBFxS5KdRjmcet#14040516 - jfs
12个回答

41

你总是可以做到

#do some stuff
print 'tasks done, now sleeping for 10 seconds'
for i in xrange(10,0,-1):
    time.sleep(1)
    print i

这段代码有一个略微让人烦恼的特性,即每个数字都会在新行上打印出来。为了避免这种情况,您可以

import sys
import time
for i in xrange(10,0,-1):
    sys.stdout.write(str(i)+' ')
    sys.stdout.flush()
    time.sleep(1)

谢谢,这很棒。你只有一个小错误我已经修复了。应该是time.sleep(1) - user1681664
1
是的,确实,答案已经固定了。 - aestrivex
3
如果出现 NameError: name 'xrange' is not defined 的错误,请使用 range 代替。在 Python 3 中,它已被重命名。 - user2529589

30

这是在Python 3.x中在控制台显示计时器的最佳方法:

import time
import sys

for remaining in range(10, 0, -1):
    sys.stdout.write("\r")
    sys.stdout.write("{:2d} seconds remaining.".format(remaining))
    sys.stdout.flush()
    time.sleep(1)

sys.stdout.write("\rComplete!            \n")

每个周期都会覆盖上一行。


18

一种简单的方法,用于清除控制台中的最后一个数字:

import time

for i in range(10,0,-1):
    print(f"{i}", end="\r", flush=True)
    time.sleep(1)

默认情况下,print函数设置end="\n",这意味着后续对print的调用将打印在新行上。您可以将其更改为end="\r"以在每次调用后替换输出(回车符"\r"在Python中如何工作)。
这里的f"{i}"是用于仅打印单个数字。您可以根据数字位数进行修改。 例如,通过添加一个空格作为后缀,它将适用于两位数字- f"{i} " 此外,使用flush意味着您不必担心缓冲问题。(print()的flush是什么?
它看起来像这样:

countdown


这很好,但是如果您输入一个大数字,比如1200,它最终会打印出8790而不是0879或879,有什么办法可以解决这个问题吗? - Oris
Oris,根据您的评论更新了答案。 - IRSHAD
更改此行代码print("{:2d}".format(i), end="\r", flush=True)print(f("{i}..."。否则,我将在此回答下方进行编辑。 - Corina Roca

8
您可以像这样实现倒计时功能:
import sys
import time

def countdown(t, step=1, msg='sleeping'):  # in seconds
    pad_str = ' ' * len('%d' % step)
    for i in range(t, 0, -step):
        print '%s for the next %d seconds %s\r' % (msg, i, pad_str),
        sys.stdout.flush()
        time.sleep(step)
    print 'Done %s for %d seconds!  %s' % (msg, t, pad_str)

回车符 \r 和逗号 , 可以让打印内容保持在同一行上(避免每个倒计时值都占据一行)。

随着秒数减少,使用 pad_str 可以确保最后一行被覆盖成空格,而不是留下最后一个或几个字符在输出缩短时残留。

最后一次打印会用完成信息覆盖最后的状态信息,并增加输出行,这样就有了延迟的证据。


1
为了防止倒计时每秒插入一个新行,应该将语句 print '%s for the next %d seconds %s\r' % (msg, i, pad_str), 更改为 sys.stdout.write( '%s for the next %d seconds %s\r' % (msg, i, pad_str),) - Jack Fleeting

2

这是我在学习Python的早期课程中学到的内容,我们玩了一下 ["/","-","|","\","|"],但原理是相同的:

import time

for i in reversed(range(0, 10)):
    time.sleep(1)
    print "%s\r" %i,

2

time.sleep()可能会因为信号的中断或其他进程/线程的调度而提前返回或延迟返回(这取决于操作系统/解释器的调度)。

为了在多次迭代中提高精度、避免大量迭代时的漂移,可以使用时钟来锁定倒计时:

#!/usr/bin/env python
import sys
import time

for i in reversed(range(1, 1001)):
    time.sleep(1 - time.time() % 1) # sleep until a whole second boundary
    sys.stderr.write('\r%4d' % i)

2

这是我做过的一个例子:

import time
a = input("How long is the countdown?")
while a != 0:
    print a
    time.sleep(1)
    a = a-1

如果你需要,你可以在结尾处添加一个else语句,并放置一个警报或其他东西。


1

另一个简单的方法,无需重复发明轮子,是使用tqdm,它会自动显示进度条:

from time import sleep
from tqdm import tqdm

for _ in tqdm(range(10)):
    sleep(1)

可选地,您可以按照自己的意愿修改加载条的显示方式。


1
当然,只需编写一个循环来打印10减去迭代计数器的值,然后让它在每次迭代时暂停1秒,并运行10次迭代。或者,为了更加灵活:
def printer(v):
    print v
def countdown_timer(duration, step=1, output_function=printer,
                    prompt='Waiting {duration} seconds.'):
    output_function(prompt.format(duration=duration))
    for i in xrange(duration/step):
        output_function(duration - step * i)

0

如果你不限制自己的睡眠时间,那么(感谢automatetheboringstuff),pyautogui有一个很棒的倒计时功能:

import pyautogui
print('Starting in ', end=''); pyautogui.countdown(3)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接