如何在经过一段时间后停止while循环?

时间:2012-11-08 16:28:03

标签: python python-2.7

如果没有达到我想要达到的目的,我将如何在5分钟后停止while循环。

while true:
    test = 0
    if test == 5:
        break
    test = test - 1

这段代码让我陷入了无休止的循环。

7 个答案:

答案 0 :(得分:86)

尝试以下方法:

import time
timeout = time.time() + 60*5   # 5 minutes from now
while True:
    test = 0
    if test == 5 or time.time() > timeout:
        break
    test = test - 1

你可能还想在这里添加一个短暂的睡眠,这样这个循环不会占用CPU(例如在循环体的开头或结尾处time.sleep(1))。

答案 1 :(得分:30)

试试这个模块:http://pypi.python.org/pypi/interruptingcow/

from interruptingcow import timeout
try:
    with timeout(60*5, exception=RuntimeError):
        while True:
            test = 0
            if test == 5:
                break
            test = test - 1
except RuntimeError:
    pass

此致

答案 2 :(得分:30)

在这种情况下,您不需要使用while True:循环。有一种更简单的方法可以直接使用时间条件:

import time

# timeout variable can be omitted, if you use specific value in the while condition
timeout = 300   # [seconds]

timeout_start = time.time()

while time.time() < timeout_start + timeout:
    test = 0
    if test == 5:
        break
    test -= 1

答案 3 :(得分:6)

Petr Krampl的答案在我看来是最好的,但需要更多关于循环的性质以及如何优化系统的使用。发生在这个主题上的初学者可能会被问题和现有答案中的逻辑和算法错误进一步混淆。

首先,让我们看一下您最初编写代码时所执行的操作:

while True:
    test = 0
    if test == 5:
        break
    test = test - 1

如果你在循环上下文中说while True,通常你的意图是永远留在循环中。如果这不是你的意图,你应该考虑循环结构的其他选项。 Petr Krampl向您展示了一种处理此问题的完全合理的方法,对于可能阅读您的代码的其他人来说,这一点要清楚得多。此外,如果您需要重新访问代码以添加或修复某些内容,几个月后您会更清楚。编写良好的代码是您文档的一部分。通常有多种方法可以做,但这并不能使所有方式在所有情况下同等有效。 while true就是一个很好的例子,特别是在这种情况下。

接下来,我们将查看原始代码中的算法错误。你在循环中做的第一件事是将0分配给test。接下来要做的是检查test的值是否为5,除非您有多个线程修改相同的内存位置,否则情况永远不会出现这种情况。线程不在讨论的范围内,但值得注意的是,代码在技术上可以工作,但即使有多个线程也会丢失,例如信号灯。无论如何,无论哨兵强迫无限循环,你都将永远坐在这个循环中。

语句test = test - 1无论它做什么都没用,因为变量在循环的下一次迭代开始时被重置。即使您将其更改为test = 5,循环仍然是无限的,因为每次都会重置该值。如果将初始化语句移到循环外部,那么它至少有机会退出。你可能想要的是这样的:

test = 0
while True:
    test = test - 1
    if test == 5:
        break

循环中语句的顺序取决于程序的逻辑。不过,它将以任何顺序工作,这是重点。

下一个问题是从0开始的潜在和可能的逻辑错误,不断减去1,然后与正数进行比较。是的,只要您了解其含义,有时候这可能实际上就是您打算做的事情,但这很可能不是您的意图。当你到达像C和其他各种语言这样的整数范围的“底部”时,较新版本的python不会回滚。它将允许您继续减去1,直到您填满系统上的可用内存或至少分配给您的进程的内存。查看以下脚本和结果:

test = 0

while True:
    test  -= 1

    if test % 100 == 0:
        print "Test = %d" % test

    if test == 5:
        print "Test = 5"
        break

产生这个:

Test = -100
Test = -200
Test = -300
Test = -400
...
Test = -21559000
Test = -21559100
Test = -21559200
Test = -21559300
...

test的值永远不会是5,所以这个循环永远不会退出。

要添加到Petr Krampl的答案,这里的版本可能更接近你实际想要的版本,除了在一段时间后退出循环:

import time

test = 0
timeout = 300   # [seconds]

timeout_start = time.time()

while time.time() < timeout_start + timeout:
    if test == 5:
        break
    test -= 1

它仍然不会基于test的值而中断,但这是一个具有合理初始条件的完全有效的循环。进一步的边界检查可以帮助您避免无缘无故地执行非常长的循环,例如:在循环输入时检查test的值是否小于5,这将立即打破循环。

应该提到的另一件事是没有其他答案得到解决。有时当你像这样循环时,你可能不想在整个分配的时间内消耗CPU。例如,假设您正在检查每秒更改的值的值。如果不引入某种延迟,则可以使用分配给进程的每个可用CPU周期。如果有必要,这很好,但是良好的设计将允许许多程序在您的系统上并行运行,而不会使可用资源负担过重。一个简单的睡眠语句将释放分配给您的进程的绝大多数CPU周期,以便其他程序可以正常工作。

以下示例不是很有用,但它确实展示了这个概念。假设您想要每秒打印一些东西。一种方法是这样的:

import time

tCurrent = time.time()

while True:
    if time.time() >= tCurrent + 1:
        print "Time = %d" % time.time()
        tCurrent = time.time()

输出将是:

Time = 1498226796
Time = 1498226797
Time = 1498226798
Time = 1498226799

进程CPU使用情况如下所示:

enter image description here

基本上没有工作,这是一个巨大的CPU使用量。这段代码对系统的其他部分更好:

import time

tCurrent = time.time()

while True:
    time.sleep(0.25) # sleep for 250 milliseconds
    if time.time() >= tCurrent + 1:
        print "Time = %d" % time.time()
        tCurrent = time.time()

输出相同:

Time = 1498226796
Time = 1498226797
Time = 1498226798
Time = 1498226799

并且CPU使用方式更低:

enter image description here

答案 4 :(得分:4)

import time

abort_after = 5 * 60
start = time.time()

while True:
  delta = time.time() - start
  if delta >= abort_after:
    break

答案 5 :(得分:0)

我想分享我正在使用的那个:

import time
# provide a waiting-time list:
lst = [1,2,7,4,5,6,4,3]
# set the timeout limit
timeLimit = 4

for i in lst:
    timeCheck = time.time()
    while True:
        time.sleep(i)
        if time.time() <= timeCheck + timeLimit:
            print ([i,'looks ok'])
            break
        else:
            print ([i,'too long'])
            break

然后你会得到:

[1, 'looks ok']
[2, 'looks ok']
[7, 'too long']
[4, 'looks ok']
[5, 'too long']
[6, 'too long']
[4, 'looks ok']
[3, 'looks ok']

答案 6 :(得分:0)

我已经读过这篇文章,但是我只是想问些问题,难道我根本就不会写东西吗? 我已经完成了5,10和20秒的测试。时间不完全准确,但确实接近实际值。

// this whole testsuite will be muted
xdescribe('Visit google', () => { 
  it('should visit google', () => { cy.visit('https://google.com/'); });
});

// this testsuite will run
describe('Visit youtube', () => {
  it('should visit youtube', () => { cy.visit('https://youtube.com/'); });

  // this testcase will be muted
  xit('is not necessary', () => { ... });
});