Stop Code After Time Period

Stop code after time period

Here you go:

import multiprocessing
import time

# Your foo function
def foo(n):
for i in range(10000 * n):
print "Tick"
time.sleep(1)

if __name__ == '__main__':
# Start foo as a process
p = multiprocessing.Process(target=foo, name="Foo", args=(10,))
p.start()

# Wait 10 seconds for foo
time.sleep(10)

# Terminate foo
p.terminate()

# Cleanup
p.join()

This will wait 10 seconds for foo and then kill it.

Update

Terminate the process only if it is running.

# If thread is active
if p.is_alive():
print "foo is running... let's kill it..."

# Terminate foo
p.terminate()

Update 2 : Recommended

Use join with timeout. If foo finishes before timeout, then main can continue.

# Wait a maximum of 10 seconds for foo
# Usage: join([timeout in seconds])
p.join(10)

# If thread is active
if p.is_alive():
print "foo is running... let's kill it..."

# Terminate foo
p.terminate()
p.join()

Kill function after a given amount of time?

Well, as always, it depends.

As you probably have already verified, both these methods work. I would say it depends on your application and correct implementation (your signalling method is a bit wrong...)

Both methods can be considered "safe" if implemented correctly. It depends if your main program outside the foo function needs to do something, or can it just sit and wait for foo to either complete or timeout. The signalling method does not allow any parallel processing, as your main program will be in foo() until it either completes or times out. BUT you need then to defuse the signal. If your foo completes in one second, your main program leaves the try/except structure, and four seconds later ... kaboom ... an exception is raised and probably uncaught. Not good.

try:
foo()
signal.alarm(0)
except TimeoutException:
print ("function terminated")

solves the problem.

I would personally prefer the multiprocessing approach. It is simpler and does not require signals and exception handling that in theory can go wrong if your program execution is not where you expect it to be when a signal is raised. If it is ok for your program to wait in join(), then you are done. However, if you want to do something in the main process while you wait, you can enter a loop, track time in a variable, check if over timeout and if so, terminate the process. You would just use join with a tiny timeout to "peek" if the process is still running.

Another method, depending on your foo(), is to use threads with a class or a global variable. If your foo keeps processing commands instead of possibly waiting for a long time for a command to finish, you can add an if clause there:

def foo():
global please_exit_now
while True:
do_stuff
do_more_stuff
if foo_is_ready:
break
if please_exit_now is True:
please_exit_now = False
return
finalise_foo
return

If do_stuff and do_more_stuff complete in a reasonable amount of time, you could then process things in your main program and just set global please_exit_now as True, and your thread would eventually notice that and exit.

I would probably just go for your multiprocessing and join, though.

Hannu

How would I stop a while loop after n amount of time?

Try the following:

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

You may also want to add a short sleep here so this loop is not hogging CPU (for example time.sleep(1) at the beginning or end of the loop body).

Break the function after certain time

I think creating a new process may be overkill. If you're on Mac or a Unix-based system, you should be able to use signal.SIGALRM to forcibly time out functions that take too long. This will work on functions that are idling for network or other issues that you absolutely can't handle by modifying your function. I have an example of using it in this answer:

Option for SSH to timeout after a short time? ClientAlive & ConnectTimeout don't seem to do what I need them to do

Editing my answer in here, though I'm not sure I'm supposed to do that:

import signal

class TimeoutException(Exception): # Custom exception class
pass

def timeout_handler(signum, frame): # Custom signal handler
raise TimeoutException

# Change the behavior of SIGALRM
signal.signal(signal.SIGALRM, timeout_handler)

for i in range(3):
# Start the timer. Once 5 seconds are over, a SIGALRM signal is sent.
signal.alarm(5)
# This try/except loop ensures that
# you'll catch TimeoutException when it's sent.
try:
A(i) # Whatever your function that might hang
except TimeoutException:
continue # continue the for loop if function A takes more than 5 second
else:
# Reset the alarm
signal.alarm(0)

This basically sets a timer for 5 seconds, then tries to execute your code. If it fails to complete before time runs out, a SIGALRM is sent, which we catch and turn into a TimeoutException. That forces you to the except block, where your program can continue.

Python: Stop Loop After Time Period

This is how i achieved it in the end:

#! /usr/bin/env python

import json
import paho.mqtt.client as mqtt
import requests
import sys
import time

max_time = 600 # 10 mins
start_time = time.time() # remember when we started

def on_connect(client, userdata, flags, rc):
client.subscribe("zigbee2mqtt/0x0015bc001b238abc")

def on_message(client, userdata, msg):
if (time.time() - start_time) > max_time:
client.loop_stop()
client.disconnect()
print("Script Ended: Ran For " + str(time.time() - start_time) + " seconds, limit was " + str(max_time))
else:
requests.post("http://www.url.uk/rpc", data = msg.payload.decode())

client = mqtt.Client()
client.connect("localhost",1883,60)

client.on_connect = on_connect
client.on_message = on_message

client.loop_forever()

End a python script after a certain amount of time

Try this. It uses signal to send a signal back within 10 seconds from the print statement. If you want it to be after the first input, move the signal calls.

import signal
from sys import exit

def trap():
print "You've fallen into a trap,you have 10 seconds to type the word \"Get me out\""
signal.signal(signal.SIGALRM, die)
signal.alarm(10)

user_input = raw_input("> ")
right_choice = "Get me out"

if *SOME CODE*:
*MORE CODE*
signal.alarm(0)

def die(signum, frame):
print "Try again"
signal.alarm(0)
exit(0)

How do i stop a while loop after a certain time in C

How about try my test code:

#include <stdio.h>
#include <time.h>
#include <unistd.h>

int main(void)
{
time_t endwait;
time_t start = time(NULL);
time_t seconds = 10; // end loop after this time has elapsed

endwait = start + seconds;

printf("start time is : %s", ctime(&start));

while (start < endwait)
{
/* Do stuff while waiting */
sleep(1); // sleep 1s.
start = time(NULL);
printf("loop time is : %s", ctime(&start));
}

printf("end time is %s", ctime(&endwait));

return 0;
}

A example outprint is :

wugq@SSDEV016:~/tools/test $ ./a.out
start time is : Fri Jan 17 17:12:57 2014
loop time is : Fri Jan 17 17:12:58 2014
loop time is : Fri Jan 17 17:12:59 2014
loop time is : Fri Jan 17 17:13:00 2014
loop time is : Fri Jan 17 17:13:01 2014
loop time is : Fri Jan 17 17:13:02 2014
loop time is : Fri Jan 17 17:13:03 2014
loop time is : Fri Jan 17 17:13:04 2014
loop time is : Fri Jan 17 17:13:05 2014
loop time is : Fri Jan 17 17:13:06 2014
loop time is : Fri Jan 17 17:13:07 2014
end time is Fri Jan 17 17:13:07 2014


Related Topics



Leave a reply



Submit