75

I have a while loop, and I want it to keep running through for 15 minutes. it is currently:

while True:
    #blah blah blah

(this runs through, and then restarts. I need it to continue doing this except after 15 minutes it exits the loop)

Thanks!

declension
  • 4,110
  • 22
  • 25
oam811
  • 755
  • 1
  • 5
  • 6

7 Answers7

156

Try this:

import time

t_end = time.time() + 60 * 15
while time.time() < t_end:
    # do whatever you do

This will run for 15 min x 60 s = 900 seconds.

Function time.time returns the current time in seconds since 1st Jan 1970. The value is in floating point, so you can even use it with sub-second precision. In the beginning the value t_end is calculated to be "now" + 15 minutes. The loop will run until the current time exceeds this preset ending time.

DrV
  • 22,637
  • 7
  • 60
  • 72
  • 1
    Thanks I tested it out originally with just 60 seconds and it stopped so I know that 15 minutes will work too. – oam811 Jun 23 '14 at 20:39
  • Another question: does the following syntax work? if keys[pygame.K_LEFT]: answer = "left" f = open("answer.rtf", "a") f.write(answer) f.close() It won't let me open up the textfile after, I'm wondering if I'm doing something wrong or if my computer is messing up. – oam811 Jun 23 '14 at 20:43
  • Finding slight syntax errors in code is very difficult from the SO comments, so maybe you should create another question. However, at least the if operation is wrong, there should be == instead of =, and the colon should be after "left". If you cannot make it work with reasonable effort, post another question. (Just make sure you do not do anything wrong with indentation.) – DrV Jun 23 '14 at 20:48
  • 5
    @oam811: use `time.monotonic()` on Python 3, to avoid unexpected delays due to machine clock adjustments (`time.time()` can be set back). – jfs Aug 31 '14 at 13:22
  • 1
    Is there a way to have it notify me if it had to skip a loop due to the time constraint? – Renel Chesak Oct 16 '17 at 17:16
  • this doesn't work when I have a for loop under the while loop. Is there a way to control that (especially if user input is required)? ie: while time.monotonic() – Shervin Rad May 12 '19 at 22:12
  • for year 2021 , I have tried this code, it works with Python 3.8 but you do not need multiply 60 to get the seconds. – Franva Sep 05 '21 at 08:43
12

If I understand you, you can do it with a datetime.timedelta -

import datetime

endTime = datetime.datetime.now() + datetime.timedelta(minutes=15)
while True:
  if datetime.datetime.now() >= endTime:
    break
  # Blah
  # Blah
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
4
import time
delay = 60*15 # For 15 minutes delay 
close_time = time.time()+delay
while True:
    # ...
    if time.time() > close_time:
        break
user16217248
  • 3,119
  • 19
  • 19
  • 37
Hasan Latif
  • 65
  • 1
  • 1
  • 12
  • 3
    Or even more simply `while close_time>time.time():` without the need for `if time.time()>close_time: break`... – Fr0zenFyr Feb 10 '18 at 09:43
3

I was looking for an easier-to-read time-loop when I encountered this question here. Something like:

for sec in max_seconds(10):
      do_something()

So I created this helper:

# allow easy time-boxing: 'for sec in max_seconds(42): do_something()'
def max_seconds(max_seconds, *, interval=1):
    interval = int(interval)
    start_time = time.time()
    end_time = start_time + max_seconds
    yield 0
    while time.time() < end_time:
        if interval > 0:
            next_time = start_time
            while next_time < time.time():
                next_time += interval
            time.sleep(int(round(next_time - time.time())))
        yield int(round(time.time() - start_time))
        if int(round(time.time() + interval)) > int(round(end_time)): 
            return

It only works with full seconds which was OK for my use-case.

Examples:

for sec in max_seconds(10) # -> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
for sec in max_seconds(10, interval=3) # -> 0, 3, 6, 9
for sec in max_seconds(7): sleep(1.5) # -> 0, 2, 4, 6
for sec in max_seconds(8): sleep(1.5) # -> 0, 2, 4, 6, 8

Be aware that interval isn't that accurate, as I only wait full seconds (sleep never was any good for me with times < 1 sec). So if your job takes 500 ms and you ask for an interval of 1 sec, you'll get called at: 0, 500ms, 2000ms, 2500ms, 4000ms and so on. One could fix this by measuring time in a loop rather than sleep() ...

Sascha N.
  • 65
  • 1
  • 6
3

For those using asyncio, an easy way is to use asyncio.wait_for():

async def my_loop():
    res = False
    while not res:
        res = await do_something()

await asyncio.wait_for(my_loop(), 10)
Sam Bull
  • 2,559
  • 1
  • 15
  • 17
0

The best solution for best performance is to use @DrV answer and the suggestion from @jfs to use time.monotonic():

    import time
    from datetime import datetime, timedelta

    count = 0
    end_time = time.monotonic() + 10
    while time.monotonic() < end_time:
        count += 1
    print(f'10 second result: {count=:,}')
    # 10 second result: count=185,519,745

    count = 0
    end_time = time.time() + 10
    while time.time() < end_time:
        count += 1
    print(f'10 second result: {count=:,}')
    # 10 second result: count=158,219,172

    count = 0
    end_time = datetime.now() + timedelta(seconds=10)
    while datetime.now() < end_time:
        count += 1
    print(f'10 second result: {count=:,}')
    # 10 second result: count=39,168,578
-4

try this:

import time
import os

n = 0
for x in range(10): #enter your value here
    print(n)
    time.sleep(1) #to wait a second
    os.system('cls') #to clear previous number
                     #use ('clear') if you are using linux or mac!
    n = n + 1