How to launch a function at regular time intervals ?

Frank Millman frank at chagford.com
Fri Aug 14 03:04:37 EDT 2009


On Aug 14, 12:52 am, David <davig... at googlemail.com> wrote:
>
> 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()

Hi David

I think that the main problem is your use of  while(1) (usually written as 
'while 1' BTW). The effect is that you create multiple copies of CStoreData 
and CTransferData, each running simultaneously. As you bind them to the same 
name each time, the previous one presumably gets garbage collected. I don't 
know if this effectively kills the running thread or not. Either way, this 
is not what you want to happen.

Here are some initial thoughts -

1. You say that you want the main program to continue running in the 
background. Personally I find it easier to think of the main program running 
in the foreground, and each of the functions running in the background.

2. As you speak of launching several functions, you may want to keep a list 
of them to make it easier to stop them at the end.

3. Instead of passing 'timestamp' as an argument to each function, it is 
probably better to call datatime.now() within the function itself.

Based on these thoughts, maybe your program should look something like 
this -

    running_functions = []

    while 1:
        if some_condition:  # start function to store data
            func = CStoreData()
            func.start()
            running_functions.append(func)

       if some_other_condition:  # start function to transfer data
            func = CTransferData()
            func.start()
            running_functions.append(func)

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

        time.sleep(0.1)  # to avoid hogging the cpu

    # stop all running functions at end
    for func in running_functions:
        func.stop()
        func.join()

I hope this gives you some ideas.

Frank





More information about the Python-list mailing list