2

Below there is some fully functioning code.

I am planning to execute this code through command line, however I would like it to end after 60 seconds.

Does anyone know the best way of going about this?

Thanks in advance.

import time
class listener(StreamListener):

    def on_data(self, data):
        try:
            print data
            saveFile = open('twitDB.csv','a')
            saveFile.write(data)
            saveFile.write('\n')
            saveFile.close()
            return True
        except BaseException, e:
            print 'failed ondata,' ,str(e)
            time.sleep(5)

    def on_error(self, status):
        print status
smeso
  • 4,165
  • 18
  • 27
user3102640
  • 39
  • 1
  • 1
  • 5
  • 1
    Memorize the time when it started, query the time in `on_data` and exit if one minutes has passed? – tobias_k Dec 25 '13 at 18:26
  • Is 'import time' at the beginning is memorising the time? Also I cant find the code for querying the time... – user3102640 Dec 25 '13 at 18:30
  • 1
    This is just a class definition. It would not "run from the command line". Do you mean from the python interpreter? – Wyrmwood Dec 25 '13 at 19:10
  • do not catch `BaseException` unless you reraise it later. Why do you want to ignore `SystemExit` or `KeyboardInterrupt`? – jfs Dec 25 '13 at 19:38
  • Basically I want the code to run for one minute every hour, I thought I would code in the cancel after 60 seconds first and then look at using command line so the code ran every hour. Would this not be correct? – user3102640 Dec 25 '13 at 19:39
  • Check out my answer in [Timeout function using threading][1] [1]: http://stackoverflow.com/a/20362397/2246694 – Chris Hagmann Dec 25 '13 at 19:51
  • @cdhagmann this code just seems to print the time, it seems a lot of code compared to examples given here is there a shorter way of doing it? – user3102640 Dec 25 '13 at 20:12
  • If you're deliberately taking some action every 5 seconds... why not just do it 12 times? Why do you want to cut it off at a specific moment? What if it's in the middle of writing the file when it gets the cutoff signal? – Karl Knechtel Dec 25 '13 at 20:27

5 Answers5

3

Try this out:

import os
import time
from datetime import datetime
from threading import Timer

def exitfunc():
    print "Exit Time", datetime.now()
    os._exit(0)

Timer(5, exitfunc).start() # exit in 5 seconds

while True: # infinite loop, replace it with your code that you want to interrupt
    print "Current Time", datetime.now()
    time.sleep(1)

There are some more examples in this StackOverflow question: Executing periodic actions in Python

I think the use of os._exit(0) is discouraged, but I'm not sure. Something about this doesn't feel kosher. It works, though.

Community
  • 1
  • 1
Ehtesh Choudhury
  • 7,452
  • 5
  • 42
  • 48
3

You could move your code into a daemon thread and exit the main thread after 60 seconds:

#!/usr/bin/env python
import time
import threading

def listen():
    print("put your code here")

t = threading.Thread(target=listen)
t.daemon = True
t.start()

time.sleep(60)
# main thread exits here. Daemon threads do not survive.
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • `failed ondata, global name 'listen' is not defined` is the error message I get – user3102640 Dec 25 '13 at 19:33
  • @user3102640: I've updated the code. Let me know if something is not clear. – jfs Dec 25 '13 at 21:13
  • I keep getting error with syntax here: ` print("put your code here")` @J.F Sebastian – user3102640 Dec 25 '13 at 21:38
  • @user3102640: the code works as is on Python 2 and Python 3. Make sure the copy-paste process hasn't added Unicode whitespace into the code (just delete whitespace before `print` and type 4 spaces manually). – jfs Dec 25 '13 at 21:44
  • That's quite neat, @J.F.Sebastian. – Ehtesh Choudhury Dec 25 '13 at 21:50
  • @J.F.Sebastian just published an edit, could you take a look. Thanks!! – user3102640 Dec 25 '13 at 23:21
  • I wouldn't recommend this approach when doing I/O operations. A daemon thread getting killed in the middle of a write is a good way to get a corrupted file. – roippi Dec 26 '13 at 00:54
  • @roippi: do you know a better alternative that allows to stop an uncooperative Python code? Please, share. – jfs Dec 26 '13 at 05:26
  • @user3102640: do not edit the answer if you have a question. [Update your question or ask a new one](http://stackoverflow.com/posts/20775624/edit) instead. – jfs Dec 26 '13 at 05:32
  • @J.F.Sebastian ah okay sorry, I am new. What the code seems to be doing is looping the code so it pulls out one tweet every 5 seconds, instead of pulling as many tweets as possible in 5 seconds. – user3102640 Dec 26 '13 at 14:38
  • @user3102640: It sounds like a [new question](http://stackoverflow.com/questions/ask) – jfs Dec 26 '13 at 15:03
0

Use signal.ALARM to get notified after a specified time.

import signal, os

def handler(signum, frame):
    print '60 seconds passed, exiting'
    cleanup_and_exit_your_code()

# Set the signal handler and a 60-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(60)

run_your_code()

From your example it is not obvious what the code will exactly do, how it will run and what kind of loop it will iterate. But you can easily implement the ALARM signal to get notified after the timeout has expired.

Tisho
  • 8,320
  • 6
  • 44
  • 52
0

This is my favorite way of doing timeout.

def timeout(func, args=None, kwargs=None, TIMEOUT=10, default=None, err=.05):
    if args is None:
        args = []
    elif hasattr(args, "__iter__") and not isinstance(args, basestring):
        args = args
    else:
        args = [args]

    kwargs = {} if kwargs is None else kwargs

    import threading
    class InterruptableThread(threading.Thread):
        def __init__(self):
            threading.Thread.__init__(self)
            self.result = None

        def run(self):
            try:
                self.result = func(*args, **kwargs)
            except:
                self.result = default

    it = InterruptableThread()
    it.start()
    it.join(TIMEOUT* (1 + err))
    if it.isAlive():
        return default
    else:
        return it.result
Chris Hagmann
  • 1,086
  • 8
  • 14
  • This is a modification of the code found here. http://code.activestate.com/recipes/473878/ – Chris Hagmann Dec 25 '13 at 19:56
  • You don't actually interrupt `func(*args, **kwargs)` call. It continues to run whether the timeout happened or not. Moreover misnamed "InterruptableThread" is not a daemon. It will prevent the program to exit if `func()` is still running. – jfs Dec 25 '13 at 19:59
  • @J.F.Sebastian How would you make this work using a `daemon` so that `func()` would timeout then? In other words, could you modify your answer so that if could take a function and arguments like my answer tries to do? – Chris Hagmann Dec 25 '13 at 20:11
  • @J.F.Sebastian How would I be able to get the results to output using that syntax? I haven't been able to figure that out still. – Chris Hagmann Dec 31 '13 at 17:07
  • @J.F.Sebastian Basically, I am still looking for a valid answer to this question that I asked, http://stackoverflow.com/q/20360795/2246694 that would incorporate `daemon` – Chris Hagmann Dec 31 '13 at 17:10
-1

I hope this is an easy way to execute a function periodically and end after 60 seconds:

import time
import os
i = 0
def executeSomething():
 global i
 print(i)
 i += 1
 time.sleep(1)
 if i == 10:
    print('End')
    os._exit(0)


while True:
 executeSomething()
Debadatta
  • 1,732
  • 2
  • 11
  • 15