【问题标题】:How can I make a time delay in Python? [duplicate]如何在 Python 中进行时间延迟? [复制]
【发布时间】:2010-09-09 00:46:35
【问题描述】:

我想知道如何在 Python 脚本中设置时间延迟。

【问题讨论】:

标签: python python-3.x delay sleep timedelay


【解决方案1】:

您可以使用sleep() function in the time module。它可以采用浮点参数进行亚秒级分辨率。

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

【讨论】:

  • 时间分辨率呢?例如,是否存在 16.66 毫秒的倍数的风险(尽管在示例中恰好是 0.1 秒,16.66 毫秒的 6 倍)?或者是例如至少保证 1 毫秒?例如,指定的 3 毫秒延迟实际上会导致 17 毫秒的延迟吗?
【解决方案2】:
import time
time.sleep(5)   # Delays for 5 seconds. You can also use a float value.

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

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 ms) 精度。现代处理器上的大多数 Linux 版本可以降低到 0.001 秒(1 毫秒)的粒度。
  • 确实如此。 tkinter 评论最好作为答案而不是在评论中呈现。我们正在这里建立一个数据库,该数据库将在未来几年内存在,人们通过谷歌寻找答案,而且很多人从来没有抽空阅读 cmets。这甚至会成为一个很好的新问题。类似于“如何在使用 tkinter 时在 Python 中进行时间延迟”或类似内容。
【解决方案3】:

困倦的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)

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

【讨论】:

    【解决方案4】:

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

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

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

    【讨论】:

      【解决方案5】:

      延迟是通过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(),但您无法创建变量时间,因为它会覆盖导入。解决这个问题的方法

      import time as t
      

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

      t.sleep()
      

      这适用于任何库。

      【讨论】:

      • 这基本上是一个关于导入的迷你教程,OP 从未询问过。这个答案可以替换为“使用time.sleep()
      【解决方案6】:

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

      在一个线程中我建议sleep function

      >>> from time import sleep
      
      >>> sleep(4)
      

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

      使用它来达到这个目的,或者只是为了延迟一个函数的执行。例如:

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

      “万岁!”在我点击 Enter 3 秒后打印出来。

      sleep 与多个线程和进程一起使用的示例

      同样,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 中没有相应的对象。您可以创建一个,但它可能由于某种原因不存在。对于一个简单的计时器来说,一个子线程比一个全新的子进程更有意义。

      【讨论】:

        【解决方案7】:

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

        第一种方法:

        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 没有提到任何这些。
        【解决方案8】:

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

        一个例子

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

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

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

        【讨论】:

          【解决方案9】:

          我知道有五种方法: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 方法,用于设置在网页上查找元素的默认等待时间。这与提出的问题完全无关。
          【解决方案10】:

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

          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()
          

          【讨论】:

            【解决方案11】:

            asyncio.sleep

            请注意,在最近的 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 运行类似的示例。您不会得到相同的运行时间结果。推荐阅读asynchronouspython编程
            • 最初的问题是关于插入延迟。那个钉子需要一把锤子,而不是异步扳手 :-)
            【解决方案12】:

            如果您想在 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:线程只能启动一次'
            【解决方案13】:

            你也可以试试这个:

            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 年的任何东西一样。
            猜你喜欢
            • 2012-03-13
            • 2013-05-04
            • 2020-06-25
            • 2014-04-03
            • 2011-03-26
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多