87

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

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

这段代码让我陷入无限循环。

4

9 回答 9

143

尝试以下操作:

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)在循环体的开头或结尾)。

于 2012-11-08T16:30:41.740 回答
47

在这种情况下,您不需要使用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
于 2014-06-19T11:41:58.560 回答
40

试试这个模块: 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
于 2012-11-08T16:32:47.503 回答
21

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 周期。如果有必要,那很好,但是好的设计将允许许多程序在您的系统上并行运行,而不会增加可用资源的负担。一个简单的 sleep 语句将释放分配给您的进程的绝大多数 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 使用率如下所示:

在此处输入图像描述

对于基本上不做任何工作来说,这是一个巨大的 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使用率要低得多:

在此处输入图像描述

于 2017-06-23T14:12:48.700 回答
6
import time

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

while True:
  delta = time.time() - start
  if delta >= abort_after:
    break
于 2012-11-08T16:31:11.680 回答
1

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

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']
于 2017-07-28T21:19:04.537 回答
0

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

import time

begin_time=0
while begin_time<5:

    begin_time+=1
    time.sleep(1.0)
print("The Work is Done")
于 2020-03-16T14:17:11.343 回答
0

我不是python专家,但我写了一个小函数来检查超时和刹车while循环

# compare now and given times older than delta
def is_time_older_than(time, delta):
    print(dt.utcnow() - time,delta)
    if (dt.utcnow() - time) > delta: 
        return True
    return False
startTime = dt.utcnow()
while True:
           print("waiting")
           if (is_time_older_than(startTime, timedelta(seconds=5)) == True):
                break

您可以在执行前记录时间而不是发送到函数作为开始时间,增量值以秒为单位(或 60*1 一分钟)它将比较差异并返回 False 或 True 就是这样

于 2022-02-05T14:29:19.640 回答
0

尝试以下操作:

from datetime import datetime, timedelta

end_time = datetime.now() + timedelta(minutes=5)
while True:
    current_time = datetime.now()
    if current_time == end_time:
        break
于 2022-02-11T17:01:06.683 回答