繁体   English   中英

几分钟后如何打破while循环?

[英]How to break a while loop after some minutes?

我的 python 程序中有一个 while 循环,我想在 5 分钟后break这个循环,我目前正在使用以下代码:

start_time = time.time()
while time.time() - start_time < 300:
    # do something

但是,每次迭代都需要额外的时间来计算time.time() - start_time < 300:部分。 例如,如果我使用具有 30000 次迭代的for循环并持续 5 分钟,则上述代码执行的迭代次数少于此次数。

我该怎么办? 我必须在 5 分钟后中断循环,我只想按时间处理这个问题,而不是通过for循环迭代。

我的一位朋友建议使用datetime包,但我不知道它是如何工作的。

上面的代码执行的迭代次数比这少。

一个可能的原因是检查时间本身需要时间。 因此,您可以不那么频繁地检查时间:

start_time = time.time()
lv = 0
while True:
    if lv == 100: # check time only once in 100 iterations
        if time.time() - start_time > 300:
            break
        else:
            lv = 0

    # do something

    lv +=1

听起来需要为我实现超时。 您可以使用内置threading模块按以下方式执行此操作:

import time
from threading import Thread, Event

stop = Event()

def function():
    while not stop.is_set():
        print('*')
        time.sleep(1)

thread = Thread(target=function)

thread.start()
thread.join(timeout=60)
stop.set()

上面的代码只是每秒打印* 60秒。

我认为使用线程和睡眠是最好的方法。 您可以使用 lambda 函数以一种简单的方式来创建一个休眠的后台线程,并简单地检查该线程是否仍在您的循环中运行(时间到时中断循环):

from threading import Thread
from time import sleep

fiveMinutes = Thread(target=lambda:sleep(300)) # 5 min sleeping thread (300 seconds)
fiveMinutes.start() # start wait time

for i in range(10**10): # <-- this represents your loop condition
    # ...
    if not fiveMinutes.is_alive(): break # break after 5 minutes elapsed
    # ...

这应该会为您的处理循环增加更少的开销,因此超时迭代应该非常接近处理相同迭代次数的有效时间。

[编辑] 线程/睡眠 vs time.time()

我做了一些更多的测试,使用休眠线程和最佳使用 time() 函数之间几乎没有区别。 每次迭代的开销小于一微秒:

from time import time

fiveMinutes = time() + 300

for i in range(10**10): # <-- this represents your loop condition
    # ...
    if time() > fiveMinutes : break # break after 5 minutes elapsed
    # ...

如果您在 1 分钟的样本中得到 3 秒的差异,我会怀疑您的逻辑的处理时间有其自身的可变性(即在循环中运行相同数量的迭代会因一次运行而异)。 要么是这样,要么您检查超时的次数比 11,311 次迭代建议的次数要多得多(可能通过检查嵌套循环)。 在我的测试中,在执​​行 41,000 次迭代的 60 秒样本中,两种方法的变化不到 0.5 秒:time() 为 +0.37 秒,线程为 +0.23 秒。

(稍后稍作修改,我想我大致同意 Alain。经过一定次数的迭代后,我从中断中获得了显着的加速,但是无论是直接使用线程、time.time 还是部分采样方法,几乎​​所有其中一些最终会降低循环时间time.time()本身可能已经相当高度优化,所以所有额外的布尔值和避免使用太多的东西可能不会改善太多)。

不知道它是否更有效,但您可以尝试一个线程和一个共享的可变对象来驱动循环。 这是 0.5 秒的测试。

import time
from threading import Thread

def myfunc(mutable_):
    time.sleep(0.5)
    mutable_.value = False
    print("done")


class Mutable:
    value = True

mutable_ = Mutable()

t = Thread(target=myfunc, args=(mutable_,))

start = time.time()
t.start()
while mutable_.value:
    print(time.time() - start)

我不知道的是,循环对mutable_.value的属性访问(不需要直接涉及线程)是否比轮询线程本身便宜得多。

现在,在我的测试中,在线程尚未更新值的情况下存在一些差异,因此与使用自己的本地时间检查相比,循环运行了一点。 可能可以将您的线程超时设置为 299.9 秒,靠近并更仔细地完成。

这是一个 v2 使用线程睡眠来获得大部分方式(即 0.49)和一个通常短路的time.time()检查以完成。

def myfunc(mutable_, looptime):
    time.sleep(looptime)
    mutable_.value = False

t = Thread(target=myfunc, args=(mutable_,.49))

t.start()
start = time.time()

while mutable_.value or (time.time() - start <= .5):
    print(time.time() - start)

试试这个:

start_time = time.time() + 300
while True:
    if time.time() > start_time:
         break

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM