How to launch a function at regular time intervals ?

Discussion in 'Python' started by David, Aug 12, 2009.

  1. David

    David Guest

    Hi all, I'm trying to launch a function at regular time intervals but
    cannot find the way to do it. Here is the code I wrote (time_interval
    is a user defined variable in seconds):

    while(1)
    timestamp=datetime.now()

    timestamp_seconds=timestamp.hour*3600+timestamp.minute*60+timestamp.second
    if timestamp_seconds % time_interval == 0: ****Call Function****

    This does not work because during the second at which the condition
    holds true, there is time to call the function several times. Since I
    want to have this function called only once every x seconds, I tried
    to add the following condition:

    if timestamp_seconds % time_interval ==0 & timestamp.microsecond == 0

    But it seems this second condition hardly ever happens (i.e. the
    timestamp variable is not updated every microsecond, therefore it can
    be 9998 then jump directly to 0003 for instance).

    Has anyone run into a similar problem (and solved it) ?

    Thanks for your help
    David, Aug 12, 2009
    #1
    1. Advertising

  2. On Wed, 12 Aug 2009 14:09:29 -0700, David wrote:
    >
    > Hi all, I'm trying to launch a function at regular time intervals but
    > cannot find the way to do it.
    >


    For what it's worth, here's how I do it:

    ---------------8<---------------

    #!/usr/bin/env python
    from time import sleep

    interval = 25 #seconds

    while not sleep(interval):
    f(spam, eggs, knight)

    ---------------8<---------------

    You might want to put the sleep inside an *obviously* infinite loop. Note
    that this works best (most accurately) for longer periods. If you need to
    account for the time spent in the actual f() calls, plug in a time.time()
    call where appropriate.

    --
    | <")-, | ''The good-enough is the enemy of the excellent.'' - John Miles
    | (_==/ |-----------,-----------------------------------------------------
    | ='- | Bartosz Wroblewski | bawr from holyhandgrenade.info or int8.org
    Bartosz Wroblewski, Aug 12, 2009
    #2
    1. Advertising

  3. David

    Dave Angel Guest

    David wrote:
    > Hi all, I'm trying to launch a function at regular time intervals but
    > cannot find the way to do it. Here is the code I wrote (time_interval
    > is a user defined variable in seconds):
    >
    > while(1)
    > timestamp=datetime.now()
    >
    > timestamp_seconds=timestamp.hour*3600+timestamp.minute*60+timestamp.second
    > if timestamp_seconds % time_interval == 0: ****Call Function****
    >
    > This does not work because during the second at which the condition
    > holds true, there is time to call the function several times. Since I
    > want to have this function called only once every x seconds, I tried
    > to add the following condition:
    >
    > if timestamp_seconds % time_interval ==0 & timestamp.microsecond == 0
    >
    > But it seems this second condition hardly ever happens (i.e. the
    > timestamp variable is not updated every microsecond, therefore it can
    > be 9998 then jump directly to 0003 for instance).
    >
    > Has anyone run into a similar problem (and solved it) ?
    >
    > Thanks for your help
    >
    >

    I'm assuming you want to call it every time_interval seconds, on
    average, with a little jitter allowed on each call, but keeping correct
    long term. In other words, if one call is a little late, you want the
    next one to still happen as close to on-time as possible.

    The general outline is something like (untested):

    times_called = 0 #number of times function has been called
    start_time = now
    while True:
    elapsed = now - start_time
    int_elapsed = int(elapsed/time_interval)
    for times_called in range(times_called, int_elapsed):
    call_the_function()
    sleep(time_interval/10) #this might give us 10% jitter,
    which is usually fine

    DaveA
    Dave Angel, Aug 13, 2009
    #3
  4. David

    Dave Angel Guest

    Re: Re: How to launch a function at regular time intervals ?

    Grant Edwards wrote:
    > On 2009-08-13, Dave Angel <> wrote:
    >
    >
    >> I'm assuming you want to call it every time_interval seconds, on
    >> average, with a little jitter allowed on each call, but keeping correct
    >> long term. In other words, if one call is a little late, you want the
    >> next one to still happen as close to on-time as possible.
    >>
    >> The general outline is something like (untested):
    >>
    >> times_called = 0 #number of times function has been called
    >> start_time = now
    >> while True:
    >> elapsed = now - start_time
    >> int_elapsed = int(elapsed/time_interval)
    >> for times_called in range(times_called, int_elapsed):
    >> call_the_function()
    >> sleep(time_interval/10) #this might give us 10% jitter, which is usually fine
    >>

    >
    > I don't understand the reasoning behind the above loop --
    > specifically the sleeping of smaller intervals than needed.
    >
    > Why not something like this:
    >
    > interval = 5.0 # interval in seconds
    > next = time.time()
    >
    > while True:
    > now = time.time()
    > if now < next:
    > time.sleep(now-next)
    > print "call_the_function()"
    > next += interval
    >
    > That will be accurate over the long term with minimal jitter.
    >
    >
    >
    >

    Two reasons I didn't take an approach like that one.

    1) I frequently need to do something else while waiting, so I tend to do
    multiple smaller sleeps. As long as each sleep is at least 100ms, the
    overhead cost is pretty small.
    2) If (occasionally) the function takes longer than the specified
    interval time, my approach does catch-up calls so the average remains
    the same.

    My loop was only a rough outline, and if neither of these considerations
    applies, yours is much nicer.

    DaveA
    Dave Angel, Aug 13, 2009
    #4
  5. David

    David Guest

    Thanks all for your answers. As suggested by Dave and Frank, I am
    indeed looking for the main program to continue running in the
    background (I have several functions I want to launch, each at a
    predefined time interval). I like Frank's solution, on the paper it
    seems it would do what I am looking for, but I cannot succeed in
    having it working. I guess I've been stuck with this problem for too
    long and can't succeed in using my brain accurately anymore... ;-)

    I defined the class as defined by Frank, and I then inserted the
    following code in a While True loop, without any other code (the idea
    is just to test Frank's solution before really using it in my
    program):

    func = MyFunction()
    func.start()

    func.stop()
    func.join()

    However I'm not getting the expected behavior. It's not taking into
    account the 30 sec wait, the function is called again and again
    without any time interval... Any idea ?

    Again, thanks a lot.
    David, Aug 13, 2009
    #5
  6. David

    MRAB Guest

    David wrote:
    > Thanks all for your answers. As suggested by Dave and Frank, I am
    > indeed looking for the main program to continue running in the
    > background (I have several functions I want to launch, each at a
    > predefined time interval). I like Frank's solution, on the paper it
    > seems it would do what I am looking for, but I cannot succeed in
    > having it working. I guess I've been stuck with this problem for too
    > long and can't succeed in using my brain accurately anymore... ;-)
    >
    > I defined the class as defined by Frank, and I then inserted the
    > following code in a While True loop, without any other code (the idea
    > is just to test Frank's solution before really using it in my
    > program):
    >
    > func = MyFunction()
    > func.start()
    >
    > func.stop()
    > func.join()
    >
    > However I'm not getting the expected behavior. It's not taking into
    > account the 30 sec wait, the function is called again and again
    > without any time interval... Any idea ?
    >
    > Again, thanks a lot.
    >

    What exactly do you mean by "I then inserted the following code in a
    While True loop"? Do you mean you put all four lines in it? If yes,
    then you're repeatedly starting then stopping the function.
    MRAB, Aug 13, 2009
    #6
  7. David

    Dave Angel Guest

    Grant Edwards wrote:
    > <snip>On 2009-08-13, Dave Angel <> wrote:
    >
    >> Grant Edwards wrote:
    >>
    >>> <snip>
    >>> interval = 5.0 # interval in seconds
    >>> next = time.time()
    >>>
    >>> while True:
    >>> now = time.time()
    >>> if now < next:
    >>> time.sleep(now-next)
    >>> print "call_the_function()"
    >>> next += interval
    >>>
    >>> That will be accurate over the long term with minimal jitter.
    >>>
    >>>

    >> <snip>
    >> 2) If (occasionally) the function takes longer than the
    >> specified interval time, my approach does catch-up calls so
    >> the average remains the same.
    >>

    >
    > I'm still confused -- doesn't mine do that as well?
    >
    >

    Yep. I missed it again. Clearly it does the catchup the next time
    around the while loop.

    DaveA
    Dave Angel, Aug 13, 2009
    #7
  8. David

    Falcolas Guest

    On Aug 12, 3:09 pm, David <> wrote:
    > Hi all, I'm trying to launch a function at regular time intervals but
    > cannot find the way to do it. Here is the code I wrote (time_interval
    > is a user defined variable in seconds):
    > [snip]
    > Has anyone run into a similar problem (and solved it) ?
    >
    > Thanks for your help


    I did - as part of a script where I needed to send load into a system
    at a steady rate. I ended up using threading to do the function calls,
    since they were not guaranteed to complete before the next interval.

    duration_start = time.time()
    interval_counter = 0
    while time.time() - duration_start < duration:
    for thread_count in xrange(numthreads):
    threading.Thread(target=exec_thread, kwargs={#snip
    unimportant#}).start()
    interval_counter += 1
    time.sleep((duration_start + (interval * interval_counter)) -
    time.time())

    Executing this loop with a simple echo and time print showed that
    there was no creep over time, and the deviation between intervals was
    around 1/100th of a second.

    I'm fairly sure I'm creating some gnarly memory leaks and such by not
    joining spent threads, but it's been a non-issue in my usage. Adding a
    list to keep track of the threads and join on complete threads would
    be fairly trivial to implement.

    I think for simpler applications, using threading.Timer to kick off
    the function would work just as well.

    ~G
    Falcolas, Aug 13, 2009
    #8
  9. David

    Dave Angel Guest

    David wrote:
    > Thanks all for your answers. As suggested by Dave and Frank, I am
    > indeed looking for the main program to continue running in the
    > background (I have several functions I want to launch, each at a
    > predefined time interval). I like Frank's solution, on the paper it
    > seems it would do what I am looking for, but I cannot succeed in
    > having it working. I guess I've been stuck with this problem for too
    > long and can't succeed in using my brain accurately anymore... ;-)
    >
    > I defined the class as defined by Frank, and I then inserted the
    > following code in a While True loop, without any other code (the idea
    > is just to test Frank's solution before really using it in my
    > program):
    >
    > func = MyFunction()
    > func.start()
    >
    > func.stop()
    > func.join()
    >
    > However I'm not getting the expected behavior. It's not taking into
    > account the 30 sec wait, the function is called again and again
    > without any time interval... Any idea ?
    >
    > Again, thanks a lot.
    >
    >
    >

    Why don't you include the code you're actually trying, instead of just
    trying to describe it. Frank's class didn't call any function, it just
    had a place to do it. So we really don't know what you're running, nor
    what about it is wrong.

    Perhaps a few well placed print statements?

    DaveA
    Dave Angel, Aug 13, 2009
    #9
  10. David

    David Guest

    On 13 août, 21:28, Dave Angel <> wrote:
    > David wrote:
    > > Thanks all for your answers. As suggested by Dave and Frank, I am
    > > indeed looking for the main program to continue running in the
    > > background (I have several functions I want to launch, each at a
    > > predefined time interval). I like Frank's solution, on the paper it
    > > seems it would do what I am looking for, but I cannot succeed in
    > > having it working. I guess I've been stuck with this problem for too
    > > long and can't succeed in using my brain accurately anymore... ;-)

    >
    > > I defined the class as defined by Frank, and I then inserted the
    > > following code in a While True loop, without any other code (the idea
    > > is just to test Frank's solution before really using it in my
    > > program):

    >
    > >     func = MyFunction()
    > >     func.start()

    >
    > >     func.stop()
    > >     func.join()

    >
    > > However I'm not getting the expected behavior. It's not taking into
    > > account the 30 sec wait, the function is called again and again
    > > without any time interval... Any idea ?

    >
    > > Again, thanks a lot.

    >
    > Why don't you include the code you're actually trying, instead of just
    > trying to describe it.  Frank's class didn't call any function, it just
    > had a place to do it.  So we really don't know what you're running, nor
    > what about it is wrong.
    >
    > Perhaps a few well placed print statements?
    >
    > DaveA


    Yes, I guess it would be more simple. Here is really what I am trying
    to do. I simplified the functions, but the purpose is to write some
    text in a local file every x seconds (here, I'm just writing the
    timestamp, i.e. a string representing the date & time, every 10
    seconds) and to transfer this file to a distant server via FTP every y
    seconds (20 seconds in the example below). My code is a little bit
    more complicated because each time I transfer the file, I delete the
    local file which is then recreated when data is written, but for
    simplicity I left this out in the code below. So, here is the code
    I've been using to test Frank's code. I've been struggling with using
    or not a While True loop or not, and everything I try seems to run
    into issues.

    import threading
    from datetime import datetime
    import ftplib

    class CFtpConnection:
    """FTP Connection parameters"""
    def __init__(self, host, port, timeout, user, passwd):
    self.host = ""
    self.port = 21
    self.timeout = 60
    self.user = ""
    self.passwd = ""

    class CStoreData(threading.Thread):
    """Write timestamp in a file every 10 seconds in separate
    thread"""

    def __init__(self, timestamp):
    threading.Thread.__init__(self)
    self.event = threading.Event()
    self.timestamp = timestamp

    def run(self):
    while not self.event.is_set():
    file_handler = open("Test.txt", 'a')
    file_handler.write(self.timestamp.strftime("%y%m%d%H%M%S
    \n"))
    file_handler.close()
    self.event.wait(10)

    def stop(self):
    self.event.set()

    class CTransferData(threading.Thread):
    """Transfer timestamp file every 20 seconds in separate thread"""

    def __init__(self, ftp_connection):
    threading.Thread.__init__(self)
    self.event = threading.Event()
    self.ftp_connection = ftp_connection

    def run(self):
    while not self.event.is_set():
    file_handler = open("Test.txt", 'r')
    Ftp_handler = ftplib.FTP('')
    Ftp_handler.connect(self.ftp_connection.host,
    self.ftp_connection.port, self.ftp_connection.timeout)
    Ftp_handler.login(self.ftp_connection.user,
    self.ftp_connection.passwd)
    Ftp_handler.storbinary("STOR Test.txt", file_handler)
    file_handler.close()
    Ftp_handler.close()
    self.event.wait(20)

    def stop(self):
    self.event.set()

    ftp_connection = CFtpConnection("", 21, 60, "", "")
    ftp_connection.host = '127.0.0.1'
    ftp_connection.user = "admin"
    ftp_connection.passwd = "admin"

    while(1):
    timestamp = datetime.now()
    func_store_data = CStoreData(timestamp)
    func_store_data.start()

    func_transfer_data = CTransferData(ftp_connection)
    func_transfer_data.start()

    func_store_data.stop()
    func_store_data.join()

    func_transfer_data.stop()
    func_transfer_data.join()
    David, Aug 13, 2009
    #10
  11. David

    David Guest

    With your help, Franck, I think I finally got it to work. This is how
    I did it:

    # In the main program, launch the 2 threads CStoreData and
    CTransferData, which will run indefinitely until they are stopped (if
    the threads were launched inside the while loop, there would be an
    infinitely growing number of threads CStoreData all doing the same
    thing, same for CTransferData)

    func_store_data = CStoreData()
    func_store_data.start()

    func_transfer_data = CTransferData()
    func_transfer_data.start()

    # While loop, just to keep the threads running until they are stopped
    at the end of the program. If there wasn't a while loop, the threads
    would be stopped right after they are launched. The while loop
    separates the "start" of the threads from the "stop" of the threads

    while 1
    if end_condition: # terminate program
    break # break out of while loop

    # Stop all running threads at end

    func_store_data.stop()
    func_store_data.join()

    func_transfer_data.stop()
    func_transfer_data.join()


    Again thanks a lot to all of you for your precious help.

    David
    David, Aug 14, 2009
    #11
  12. David

    David Guest

    With your help, Franck, I think I finally got it to work. This is how
    I did it:

    # In the main program, launch the 2 threads CStoreData and
    CTransferData, which will run indefinitely until they are stopped (if
    the threads were launched inside the while loop, there would be an
    infinitely growing number of threads CStoreData all doing the same
    thing, same for CTransferData)

    func_store_data = CStoreData()
    func_store_data.start()

    func_transfer_data = CTransferData()
    func_transfer_data.start()

    # While loop, just to keep the threads running until they are stopped
    at the end of the program. If there wasn't a while loop, the threads
    would be stopped right after they are launched. The while loop
    separates the "start" of the threads from the "stop" of the threads

    while 1
    if end_condition: # terminate program
    break # break out of while loop

    # Stop all running threads at end

    func_store_data.stop()
    func_store_data.join()

    func_transfer_data.stop()
    func_transfer_data.join()


    Again thanks a lot to all of you for your precious help.

    David
    David, Aug 14, 2009
    #12
  13. David

    David Guest

    With your help, Franck, I think I finally got it to work. This is how
    I did it:

    # In the main program, launch the 2 threads CStoreData and
    CTransferData, which will run indefinitely until they are stopped (if
    the threads were launched inside the while loop, there would be an
    infinitely growing number of threads CStoreData all doing the same
    thing, same for CTransferData)

    func_store_data = CStoreData()
    func_store_data.start()

    func_transfer_data = CTransferData()
    func_transfer_data.start()

    # While loop, just to keep the threads running until they are stopped
    at the end of the program. If there wasn't a while loop, the threads
    would be stopped right after they are launched. The while loop
    separates the "start" of the threads from the "stop" of the threads

    while 1
    if end_condition: # terminate program
    break # break out of while loop

    # Stop all running threads at end

    func_store_data.stop()
    func_store_data.join()

    func_transfer_data.stop()
    func_transfer_data.join()


    Again thanks a lot to all of you for your precious help.

    David
    David, Aug 14, 2009
    #13
  14. David

    MRAB Guest

    David wrote:
    > With your help, Franck, I think I finally got it to work. This is how
    > I did it:
    >
    > # In the main program, launch the 2 threads CStoreData and
    > CTransferData, which will run indefinitely until they are stopped (if
    > the threads were launched inside the while loop, there would be an
    > infinitely growing number of threads CStoreData all doing the same
    > thing, same for CTransferData)
    >
    > func_store_data = CStoreData()
    > func_store_data.start()
    >
    > func_transfer_data = CTransferData()
    > func_transfer_data.start()
    >
    > # While loop, just to keep the threads running until they are stopped
    > at the end of the program. If there wasn't a while loop, the threads
    > would be stopped right after they are launched. The while loop
    > separates the "start" of the threads from the "stop" of the threads
    >
    > while 1
    > if end_condition: # terminate program
    > break # break out of while loop
    >

    You might want to insert a sleep or something in there, otherwise you'll
    be it'll consume a lot of CPU time doing nothing (a 'busy wait').

    > # Stop all running threads at end
    >
    > func_store_data.stop()
    > func_store_data.join()
    >
    > func_transfer_data.stop()
    > func_transfer_data.join()
    >
    >
    > Again thanks a lot to all of you for your precious help.
    >
    MRAB, Aug 14, 2009
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?am9l?=

    Updating IE Page at regular intervals

    =?Utf-8?B?am9l?=, Jan 21, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    345
    Steve C. Orr [MVP, MCSD]
    Jan 21, 2004
  2. Peter Strøiman
    Replies:
    3
    Views:
    5,853
    Steven Cheng[MSFT]
    Aug 8, 2005
  3. Bobby Edward

    Code that runs at regular intervals - How?

    Bobby Edward, Jan 3, 2009, in forum: ASP .Net
    Replies:
    3
    Views:
    301
    Bobby Edward
    Jan 3, 2009
  4. KevinSimonson
    Replies:
    6
    Views:
    1,264
  5. Cognition Peon

    IP packet count at regular intervals of time.

    Cognition Peon, Nov 24, 2003, in forum: Perl Misc
    Replies:
    0
    Views:
    121
    Cognition Peon
    Nov 24, 2003
Loading...

Share This Page