views:

513

answers:

7

Is there any way to make a function (the ones I'm thinking of are in the style of the simple ones I've made which generate the fibonnacci sequence from 0 to a point, and all the primes between two points) run indefinitely. E.g. until I press a certain key or until a time has passed, rather than until a number reaches a certain point?

Also, if it is based on time then is there any way I could just extend the time and start it going from that point again, rather than having to start again from 0? I am aware there is a time module, i just don't know much about it.

A: 

As in almost all languages:

while True:
  # check what you want and eventually break
  print nextValue()

The second part of your question is more interesting:

Also, if it is based on time then is there anyway I could just extend the time and start it going from that point again rather than having to start again from 0

you can use a yield instead of return in the function nextValue()

Davide
Except that by "start it going from that point again" could be interpreted to mean "execute the program at a later date resuming from the last computed output"...
Don Wakefield
+1  A: 

The simplest way is just to write a program with an infinite loop, and then hit control-C to stop it. Without more description it's hard to know if this works for you.

If you do it time-based, you don't need a generator. You can just have it pause for user input, something like a "Continue? [y/n]", read from stdin, and depending on what you get either exit the loop or not.

lacker
A: 

If you use a child thread to run the function while the main thread waits for character input it should work. Just remember to have something that stops the child thread (in the example below the global runthread)

For example:

import threading, time
runthread = 1
def myfun():
   while runthread:
      print "A"
      time.sleep(.1)

t = threading.Thread(target=myfun)
t.start()
raw_input("")
runthread = 0
t.join()

does just that

Andrew Cox
A: 

If you really want your function to run and still wants user (or system) input, you have two solutions:

  1. multi-thread
  2. multi-process

It will depend on how fine the interaction. If you just want to interrupt the function and don't care about the exit, then multi-process is fine.

In both cases, you can rely on some shared resources (file or shared memory for multi-thread, variable with associated mutex for multi-thread) and check for the state of that resource regularly in your function. If it is set up to tell you to quit, just do it.

Example on multi-thread:

from threading import Thread, Lock
from time import sleep

class MyFct(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.mutex = Lock()
        self._quit = False

    def stopped(self):
        self.mutex.acquire()
        val = self._quit
        self.mutex.release()
        return val

    def stop(self):
        self.mutex.acquire()
        self._quit = True
        self.mutex.release()

    def run(self):
        i = 1
        j = 1
        print i
        print j
        while True:
            if self.stopped():
                return
            i,j = j,i+j
            print j

def main_fct():
    t = MyFct()
    t.start()
    sleep(1)
    t.stop()
    t.join()
    print "Exited"

if __name__ == "__main__":
    main_fct()
PierreBdR
A: 

If you want to exit based on time, you can use the signal module's alarm(time) function, and the catch the SIGALRM - here's an example http://docs.python.org/library/signal.html#example

You can let the user interrupt the program in a sane manner by catching KeyboardInterrupt. Simply catch the KeyboardInterrupt exception from outside you main loop, and do whatever cleanup you want.

If you want to continue later where you left off, you will have to add some sort persistence. I would pickle a data structure to disk, that you could read back in to continue the operations.

I haven't tried anything like this, but you could look into using something like memoizing, and caching to the disk.

JimB
yep ... I was going to answer that, but it's not python ... it's UNIX !
PierreBdR
A: 

You could do something like this to generate fibonnacci numbers for 1 second then stop.

fibonnacci = [1,1]
stoptime = time.time() + 1 # set stop time to 1 second in the future
while time.time() < stoptime:
  fibonnacci.append(fibonnacci[-1]+fibonnacci[-2])

print "Generated %s numbers, the last one was %s." % (len(fibonnacci),fibonnacci[-1])

I'm not sure how efficient it is to call time.time() in every loop - depending on the what you are doing inside the loop, it might end up taking a lot of the performance away.

rjmunro
A: 

You could use a generator for this:

def finished():
    "Define your exit condition here"
    return ...

def count(i=0):
    while not finished():
        yield i
        i += 1

for i in count():
    print i

If you want to change the exit condition you could pass a value back into the generator function and use that value to determine when to exit.

unbeknown