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
Python: Use MySQLdb to Import a MySQL Table as a Dictionary
Python Split String into Multiple String
Get List of All Routes Defined in the Flask App
Is There a Module for Balanced Binary Tree in Python's Standard Library
Iterating Through Two Lists in Django Templates
Python How to Read N Number of Lines at a Time
Changing Order of Unit Tests in Python
What's the Best Way to Duplicate Fork() in Windows
Paging/Scrolling Through Set of 2D Heat Maps in Matplotlib
Remove Duplicate Rows from Pandas Dataframe Where Only Some Columns Have the Same Value
String Comparison Doesn't Seem to Work for Lines Read from a File
Differencebetween a Pandas Series and a Single-Column Dataframe
Cannot Use Geometry Manager Pack Inside