ChatGPT解决这个技术问题 Extra ChatGPT

我如何做一个时间延迟? [复制]

这个问题在这里已经有了答案:如何让我的程序休眠 50 毫秒? (6 个回答) 2 年前关闭。

如何在 Python 脚本中设置时间延迟?


M
Mateen Ulhaq

这会延迟 2.5 秒:

import time
time.sleep(2.5)

这是另一个大约每分钟运行一次的示例:

import time
while True:
    print("This prints once a minute.")
    time.sleep(60) # Delay for 1 minute (60 seconds).

如果你需要一些条件发生。最好是用户 threading.Event.wait。
嗯......它的打印频率会低于这个频率,因为它需要时间来打印和处理所有需要的缓冲区(可能进行内核上下文切换),并注册警报信号,但是......是的。每分钟不到一次。
当使用 tkinter 作为图形用户界面时, sleep() 不会完成这项工作 - 使用 after() 代替: tkinter.Tk.after(yourrootwindow,60000) 或 yourrootwindow.after(60000)
值得一提的是,在 Windows 中,您可以期望的最佳粒度约为 0.015 秒(15 毫秒)精度。现代处理器上的大多数 Linux 版本都可以降低到 0.001 秒 (1 ms) 的粒度。
的确。 tkinter 评论最好作为答案而不是在评论中呈现。我们正在这里建立一个数据库,该数据库将在未来几年内存在,人们通过谷歌寻找答案,而且很多人从来没有抽空阅读评论。这甚至会成为一个很好的新问题。类似于“如何在使用 tkinter 时在 Python 中进行时间延迟”或类似内容。
M
Mateen Ulhaq

使用 time 模块中的 sleep()。它可以采用浮点参数进行亚秒级分辨率。

from time import sleep
sleep(0.1)  # Time in seconds

时间分辨率呢?例如,是否存在 16.66 毫秒的倍数的风险(尽管在示例中恰好是 0.1 秒,16.66 毫秒的 6 倍)?或者至少保证 1 毫秒?例如,指定的 3 毫秒延迟实际上会导致 17 毫秒的延迟吗?
P
Peter Mortensen

如何在 Python 中进行时间延迟?

在一个线程中,我建议使用 sleep function

>>> from time import sleep

>>> sleep(4)

这个函数实际上暂停了操作系统调用它的线程的处理,允许其他线程和进程在它休眠时执行。

将其用于该目的,或仅用于延迟执行功能。例如:

>>> def party_time():
...     print('hooray!')
...
>>> sleep(3); party_time()
hooray!

“万岁!”在我按 Enter 后 3 秒打印。

使用带多个线程和进程的睡眠示例

同样,sleep 暂停您的线程 - 它使用几乎为零的处理能力。

为了演示,创建一个这样的脚本(我首先在交互式 Python 3.5 shell 中尝试了这个,但由于某种原因子进程找不到 party_later 函数):

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, as_completed
from time import sleep, time

def party_later(kind='', n=''):
    sleep(3)
    return kind + n + ' party time!: ' + __name__

def main():
    with ProcessPoolExecutor() as proc_executor:
        with ThreadPoolExecutor() as thread_executor:
            start_time = time()
            proc_future1 = proc_executor.submit(party_later, kind='proc', n='1')
            proc_future2 = proc_executor.submit(party_later, kind='proc', n='2')
            thread_future1 = thread_executor.submit(party_later, kind='thread', n='1')
            thread_future2 = thread_executor.submit(party_later, kind='thread', n='2')
            for f in as_completed([
              proc_future1, proc_future2, thread_future1, thread_future2,]):
                print(f.result())
            end_time = time()
    print('total time to execute four 3-sec functions:', end_time - start_time)

if __name__ == '__main__':
    main()

此脚本的示例输出:

thread1 party time!: __main__
thread2 party time!: __main__
proc1 party time!: __mp_main__
proc2 party time!: __mp_main__
total time to execute four 3-sec functions: 3.4519670009613037

多线程

您可以使用 Timer threading 对象触发稍后在单独线程中调用的函数:

>>> from threading import Timer
>>> t = Timer(3, party_time, args=None, kwargs=None)
>>> t.start()
>>>
>>> hooray!

>>>

空行说明该函数打印到我的标准输出,我必须按 Enter 以确保我在提示符下。

这种方法的好处是,当 Timer 线程等待时,我可以做其他事情,在这种情况下,在函数执行之前按一次 Enter(请参阅第一个空提示)。

multiprocessing library 中没有相应的对象。您可以创建一个,但它可能由于某种原因不存在。对于一个简单的计时器来说,一个子线程比一个全新的子进程更有意义。


H
Humble_boy

延迟也可以通过以下方法实现。

第一种方法:

import time
time.sleep(5) # Delay for 5 seconds.

第二种延迟方法是使用隐式等待方法:

 driver.implicitly_wait(5)

当您必须等到特定操作完成或找到元素时,第三种方法更有用:

self.wait.until(EC.presence_of_element_located((By.ID, 'UserName'))

第二种和第三种方法本身不是 Python,而是与 selenium 相关的。当您进行 E2E 测试时,您会使用它们。 OP没有提到任何这些。
T
Trooper Z

我知道有五种方法:time.sleep()pygame.time.wait()、matplotlib 的 pyplot.pause().after()asyncio.sleep()

time.sleep() 示例(如果使用 tkinter,请勿使用):

import time
print('Hello')
time.sleep(5) # Number of seconds
print('Bye')

pygame.time.wait() 示例(如果您不使用 pygame 窗口,则不推荐,但您可以立即退出窗口):

import pygame
# If you are going to use the time module
# don't do "from pygame import *"
pygame.init()
print('Hello')
pygame.time.wait(5000) # Milliseconds
print('Bye')

matplotlib 的函数 pyplot.pause() 示例(如果您不使用图形,则不推荐,但您可以立即退出图形):

import matplotlib
print('Hello')
matplotlib.pyplot.pause(5) # Seconds
print('Bye')

.after() 方法(最好使用 Tkinter):

import tkinter as tk # Tkinter for Python 2
root = tk.Tk()
print('Hello')
def ohhi():
    print('Oh, hi!')
root.after(5000, ohhi) # Milliseconds and then a function
print('Bye')

最后,asyncio.sleep() 方法:

import asyncio
asyncio.sleep(5)

driver.implicitly_wait() 是一种 selenium webdriver 方法,用于设置在网页上查找元素的默认等待时间。这与提出的问题完全无关。
asyncio.sleep 不是这样工作的。在事件循环中必须await它。这不是通用延迟。
P
Peter Mortensen

困倦的 generator 有点乐趣。

问题是关于时间延迟。它可以是固定时间,但在某些情况下,我们可能需要测量自上次以来的延迟。这是一种可能的解决方案:

自上次以来测量的延迟(定期醒来)

情况可能是,我们希望尽可能有规律地做某事,并且不想为代码周围的所有 last_timenext_time 东西烦恼。

蜂鸣器发生器

以下代码 (sleepy.py) 定义了一个 buzzergen 生成器:

import time
from itertools import count

def buzzergen(period):
    nexttime = time.time() + period
    for i in count():
        now = time.time()
        tosleep = nexttime - now
        if tosleep > 0:
            time.sleep(tosleep)
            nexttime += period
        else:
            nexttime = now + period
        yield i, nexttime

调用常规蜂鸣器

from sleepy import buzzergen
import time
buzzer = buzzergen(3) # Planning to wake up each 3 seconds
print time.time()
buzzer.next()
print time.time()
time.sleep(2)
buzzer.next()
print time.time()
time.sleep(5) # Sleeping a bit longer than usually
buzzer.next()
print time.time()
buzzer.next()
print time.time()

运行它,我们看到:

1400102636.46
1400102639.46
1400102642.46
1400102647.47
1400102650.47

我们也可以直接循环使用:

import random
for ring in buzzergen(3):
    print "now", time.time()
    print "ring", ring
    time.sleep(random.choice([0, 2, 4, 6]))

运行它我们可能会看到:

now 1400102751.46
ring (0, 1400102754.461676)
now 1400102754.46
ring (1, 1400102757.461676)
now 1400102757.46
ring (2, 1400102760.461676)
now 1400102760.46
ring (3, 1400102763.461676)
now 1400102766.47
ring (4, 1400102769.47115)
now 1400102769.47
ring (5, 1400102772.47115)
now 1400102772.47
ring (6, 1400102775.47115)
now 1400102775.47
ring (7, 1400102778.47115)

正如我们所看到的,这个蜂鸣器不是太死板,即使我们睡过头并超出了正常的日程安排,也能让我们赶上规律的困倦时间。


P
Peter Mortensen

Python 标准库中的 Tkinter 库是一个可以导入的交互式工具。基本上,您可以创建按钮和框以及弹出窗口和显示为您使用代码操作的窗口的东西。

如果您使用 Tkinter,不要使用 time.sleep(),因为它会破坏您的程序。这发生在我身上。相反,请使用 root.after() 并将值替换为多少秒,以毫秒为单位。例如,time.sleep(1) 相当于 Tkinter 中的 root.after(1000)

否则,许多答案都指出了time.sleep(),这是要走的路。


M
Matthew Miles

延迟是通过 time library 完成的,特别是 time.sleep() 函数。

让它等待一秒钟:

from time import sleep
sleep(1)

这是有效的,因为这样做:

from time import sleep

您从 time library 中提取 sleep function only,这意味着您可以通过以下方式调用它:

sleep(seconds)

而不必打字

time.sleep()

打字太长了。

使用此方法,您将无法访问 time library 的其他功能,并且您不能拥有名为 sleep 的变量。但是您可以创建一个名为 time 的变量。

如果您只需要模块的某些部分,则执行 from [library] import [function] (, [function2]) 非常好。

你同样可以这样做:

import time
time.sleep(1)

只要您输入 time.[function](),您就可以访问 time library 的其他功能,例如 time.clock(),但您无法创建变量 time,因为它会覆盖导入。解决这个问题

import time as t

这将允许您将 time library 引用为 t,从而允许您执行以下操作:

t.sleep()

这适用于任何图书馆。


这基本上是一个关于导入的迷你教程,OP 从未询问过。此答案可以替换为“使用 time.sleep()
P
Peter Mortensen

如果您想在 Python 脚本中设置时间延迟:

像这样使用 time.sleepEvent().wait

from threading import Event
from time import sleep

delay_in_sec = 2

# Use time.sleep like this
sleep(delay_in_sec)         # Returns None
print(f'slept for {delay_in_sec} seconds')

# Or use Event().wait like this
Event().wait(delay_in_sec)  # Returns False
print(f'waited for {delay_in_sec} seconds')

但是,如果您想延迟函数的执行,请执行以下操作:

像这样使用 threading.Timer

from threading import Timer

delay_in_sec = 2

def hello(delay_in_sec):
    print(f'function called after {delay_in_sec} seconds')

t = Timer(delay_in_sec, hello, [delay_in_sec])  # Hello function will be called 2 seconds later with [delay_in_sec] as the *args parameter
t.start()  # Returns None
print("Started")

输出:

Started
function called after 2 seconds

为什么使用后一种方法?

它不会停止整个脚本的执行(您传递给它的函数除外)。

启动计时器后,您也可以通过执行 timer_obj.cancel() 来停止它。


它第一次工作..第二次给出错误'RuntimeError:线程只能启动一次'
P
Peter Mortensen

异步睡眠

请注意,在最近的 Python 版本(Python 3.4 或更高版本)中,您可以使用 asyncio.sleep。它与异步编程和asyncio有关。查看下一个示例:

import asyncio
from datetime import datetime

@asyncio.coroutine
def countdown(iteration_name, countdown_sec):
    """
    Just count for some countdown_sec seconds and do nothing else
    """
    while countdown_sec > 0:
       print(f'{iteration_name} iterates: {countdown_sec} seconds')
       yield from asyncio.sleep(1)
       countdown_sec -= 1

loop = asyncio.get_event_loop()
tasks = [asyncio.ensure_future(countdown('First Count', 2)),
         asyncio.ensure_future(countdown('Second Count', 3))]

start_time = datetime.utcnow()

# Run both methods. How much time will both run...?
loop.run_until_complete(asyncio.wait(tasks))

loop.close()

print(f'total running time: {datetime.utcnow() - start_time}')

我们可能会认为它会在第一种方法中“休眠”2 秒,然后在第二种方法中“休眠”3 秒,这段代码总共运行了 5 秒。但它会打印:

total_running_time: 0:00:03.01286

建议阅读 asyncio official documentation 了解更多详情。


为什么这比 time.sleep() 好?
尝试使用 time.sleep 运行类似的示例。您不会得到相同的运行时间结果。推荐阅读关于python编程的asynchronous
最初的问题是关于插入延迟。那个钉子需要一把锤子,而不是异步扳手:-)
C
Community

虽然其他人都建议使用事实上的 time 模块,但我想我会使用 matplotlibpyplot 函数 pause 分享一个不同的方法。

一个例子

from matplotlib import pyplot as plt
plt.pause(5)    # Pauses the program for 5 seconds

通常,这用于防止情节在绘制后立即消失或制作粗略的动画。

如果您已经导入了 matplotlib,这将为您节省一个 import


P
Peter Mortensen

这是时间延迟的一个简单示例:

import time

def delay(period='5'):
    # If the user enters nothing, it'll wait 5 seconds
    try:
        # If the user not enters a int, I'll just return ''
        time.sleep(period)
    except:
        return ''

另一个,在 Tkinter 中:

import tkinter

def tick():
    pass

root = Tk()
delay = 100 # Time in milliseconds
root.after(delay, tick)
root.mainloop()

P
Peter Mortensen

你也可以试试这个:

import time
# The time now
start = time.time() 
while time.time() - start < 10: # Run 1- seconds
    pass
# Do the job

现在外壳不会崩溃或没有反应。


不要使用此解决方案。它可能在技术上有效,但它会吃掉你的 CPU。现代硬件和操作系统有更好的方法来创建不占用系统资源的时间延迟。请改用 time.sleep()。
是的,现代的,就像过去 4-5 年的任何东西一样。