添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

在Python中打破/中断一个time.sleep()。

79 人关注

我需要用ctrl c从time.sleep()中断开。

While 1:
    time.sleep(60)

在上面的代码中,当控件进入time.sleep函数时,需要整整60秒的时间让python处理CTRL C的问题。

是否有任何优雅的方法来做到这一点。 这样我就可以在控件处于time.sleep功能时中断。

我是在一个传统的实现上测试的,它在windows 2000上使用python 2.2,这造成了所有的麻烦。如果我使用的是更高版本的Python,CTRL C就会中断sleep()。我做了一个快速的黑客,在for循环中调用sleep(1),这暂时解决了我的问题

3 个评论
Anuj
它每60秒监测一次,所以为了退出PGM,用户按CTRL C,但他必须等待60秒才能得到提示。
DS.
在大多数系统中,Ctrl-C会中断睡眠。在Unix和Mac上,它当然会这样做。你在哪个系统上?
for i in range(60): sleep(1) 我认为这样更好。
python
Anuj
Anuj
发布于 2011-02-25
7 个回答
thom_nic
thom_nic
发布于 2021-11-29
已采纳
0 人赞同

The correct 答案是使用python stdlib的 threading.Event

当然,你可以调低你的睡眠间隔,使你的睡眠时间非常短,但如果你 实际上 想每60秒运行一次你的循环? 那么你需要做更多的工作来确定是该运行还是继续睡觉。 此外,你 still 技术上阻断,但只在短时间内。 与 threading.Event 形成对比。

from threading import Event
exit = Event()
def main():
    while not exit.is_set():
      do_my_thing()
      exit.wait(60)
    print("All done!")
    # perform any cleanup here
def quit(signo, _frame):
    print("Interrupted by %d, shutting down" % signo)
    exit.set()
if __name__ == '__main__':
    import signal
    for sig in ('TERM', 'HUP', 'INT'):
        signal.signal(getattr(signal, 'SIG'+sig), quit);
    main()

当信号处理程序调用exit.set()时,主线程的wait()调用将立即 be interrupted.

现在,你可以用Event来表示还有更多工作要做,等等。但在这种情况下,它可以作为一个方便的指标,表明我们想退出(例如,while not exit.is_set()部分)。

你也可以选择在你的while循环之后放置任何清理代码。

user
注意:在调用 exit.set() 后, exit.wait() 的调用将不再对事件对象 exit 起作用,除非你调用 exit.clear() ,参考。 线程::事件对象
我认为这是在每60秒+单次 do_my_thing() 执行时间的情况下调用 do_my_thing() 。因此,如果 do_my_thing() 总是需要5秒,它将每65秒执行一次。
@desowin 正确...要使它每60秒(大约)发射一次,你应该设置一个变量为它第一次发射的时间 start_time = time.time() ,在循环中放一个计数器 cycle_num += 1 ,然后做 wait(max(0, start_time+60*cycle_num-time.time())) ,而不仅仅是60。 替换代码3】的部分只是为了避免出现负的等待时间。 当然,你也应该让那个60成为一个变量参数;哦,不要调用一个函数 exit !
@travc 另外,应该注意的是,time.monotonic()应该比time.time()优先。当系统时钟被调整/改变时,使用time.time()会破坏计时。
这很美。
Andreas Jung
Andreas Jung
发布于 2021-11-29
0 人赞同

不知道这段代码的意义是什么--但如果有必要的话,可以使用更短的sleep()间隔,并在其周围放一个for循环。

for i in range(60):
   sleep(1)

抓住键盘中断使用try...except来处理异常是直截了当的

Ron
这可以扩展为更快的反应:for i in range(sec/0.1): sleep(0.1)
这可能对他的天真例子有效,但有很多情况下,我们不能只是简单的投票速度。
这是个黑客。请看@thom_nic的正确答案。
这种反复尝试的方法被称为 "轮询"。只要有可能,就应该避免这种做法,因为它通常会造成CPU资源的浪费。系统提供了替代机制,例如@thorn_nic所使用的机制。这些都是非常有效的,因为从深层次上讲,它们利用了特殊的硬件指令和中断。
下面是解决方案: ` for i in range(360): try: sleep(1) except KeyboardInterrupt: sys.exit(0)`.
Pier1 Sys
Pier1 Sys
发布于 2021-11-29
0 人赞同

当用户点击中断键Ctrl-C时,就会引发KeyboardInterrupt异常。在python中,这是从一个SIGINT信号转化而来的。这意味着,你可以使用信号模块来处理它。

import signal
def handler(signum, frame):
    print("do whatever, like call thread.interrupt_main()")
signal.signal(signal.SIGINT, handler)
print("Waiting for SIGINT...")
signal.pause()

这样,你就可以在收到键盘中断时做你想做的事情。

Anuj
中断只有在它从睡眠中醒来后才会被处理...:(
我认为你的代码中可能有其他问题,因为我无法重现它,或者你可以在这里的标准文档中看到。 docs.python.org/library/time.html#time.sleep 例如,这是否发生在不同的线程上,也许是一些不是背景线程的东西?
这只适用于你只有一个主线程的情况。如果你有其他线程启动,信号处理程序不会处理其他正在睡眠的线程。
不幸的是,这并没有中断 time.sleep() 的调用,尽管你的信号处理函数会被执行。 唯一的选择是从信号句柄中调用 sys.exit() ,但这是非常粗暴的做法。
替换代码0】在C语言中可以被信号处理程序打断,但在Python中,它不会。引自Python 3.7官方文档。 "在3.5版本中改变了:现在,即使睡眠被信号打断,该函数也至少要睡几秒钟,除非信号处理程序引发异常(原理见PEP 475)。"
nico
nico
发布于 2021-11-29
0 人赞同

最优雅的解决方案当然是 threading.Event ,不过如果你只需要一个快速的黑客,这个代码也很好用。

import time
def main():
    print("It’s time !")
if __name__ == "__main__":
    print("press ctrl-c to stop")
    loop_forever = True
    while loop_forever:
        main()
            time.sleep(60)
        except KeyboardInterrupt:
            loop_forever = False
    
在我的测试中,在带有Python 3.8的Linux上,当我在睡眠过程中点击control-c时,KeyboardInterrupt直到睡眠完成后才被调用。
nico
奇怪的是,它对你不起作用。我在macOS、Raspberry Pi OS和Ubuntu上都试过了,对我来说很有效。
我正在使用完全相同的解决方案,它在Debian上工作。
johnbaum
johnbaum
发布于 2021-11-29
0 人赞同

我在Linux下用2.5、2.6、3版本的Python尝试了你的代码,当按下CTRL-C时,都出现了 "KeyboardInterrupt "异常。

也许是一些异常处理捕获了中断,或者你的问题是这样的。 为什么KeyboardInterrupt在python中不工作?

xendi
xendi
发布于 2021-11-29
0 人赞同

Figured I'd throw this in.

import time
def sleep(seconds):
    for i in range(seconds):
            time.sleep(1)
        except KeyboardInterrupt:
            print("Oh! You have sent a Keyboard Interrupt to me.\nBye, Bye")
            break
sleep(60)
    
我想你是想用 "break "而不是 "continue "来停止睡眠。 使用continue会导致它直接跳到循环的下一个迭代,这基本上是一个noop。
Pithikos
Pithikos
发布于 2021-11-29
0 人赞同

根据@Andreas Jung的回答

        for i in range(360):