1

I've been reading up on threading and tried implementing it into my code however I'm not sure if the way I'm doing it, is the best practise.

My code simply imports a self scripted package which pulls weather data and runs the package every 60 seconds thereafter.

I plan on running multiple packages which gather data at once, when I have worked out a good code technique.

from package.weather import weatherapi
import threading

def update():
  weatherapi()
  threading.Timer(60, update).start()

update()
  1. Firstly it just seems messy and if I wanted more packages running in a thread, I'd need to create another update function
  2. Secondly I'm not able to kill my process

If anyone has any suggestions, it would be greatly appreciated.

  • Why not just use `time.sleep` for the delay? BTW if you want to exit a process without killing all threads, set their `daemon` flag to `True` before starting them. – MisterMiyagi Jul 03 '16 at 18:04
  • Also have a look at this: http://stackoverflow.com/q/3393612/1025391 – moooeeeep Jul 03 '16 at 18:27

2 Answers2

0

This is a really bad use of Threading.timer. You're constantly starting new threads, when you just want one thread to do something regularly. This code is equivalent:

from package.weather import weatherapi
import threading
import time

def update():
  while True:
    weatherapi()
    time.sleep(60)

WHEATHER_THREAD=threading.Thread(target=update)
WHEATHER_THREAD.daemon = True  # main can exit while thread is still running
WHEATHER_THREAD.start()

Since threads all use the same namespace, you can also make do with just one function.

UPDATE_CALLABLES = [weatherapi]  # add new functions to have them called by update
def update():
  while True:
    for func in UPDATE_CALLABLES:
      func()
    time.sleep(60)

Note that UPDATE_CALLABLES can also be appended while the Thread is already running.

MisterMiyagi
  • 44,374
  • 10
  • 104
  • 119
0

A class like this does what you want:

import threading

class Interval:
    def __init__(self):
        self.api=[]
        self.interval=60
        self.timer=self

    def set_api(self,api):
        self.api=api
    def set_interval(self,interval):
        self.interval=interval
    def cancel(self):
        pass
    def stop(self):
        self.timer.cancel()

    def update(self):
        for api in self.api:
            api()
        self.timer = threading.Timer(self.interval,self.update).start()

# Create instance and start with default parameters
interval=Interval()
interval.update()

# Later on change the list of items to call
interval.set_api([thisApi,thatApi])

# Later on still change the interval between calls
interval.set_interval(30)

# When you have had enough, cancel the timer
interval.stop()

Note that it still creates a new thread for each interval timed, but you can change the list of calls made at any time and stop it repeating at any time.

quamrana
  • 37,849
  • 12
  • 53
  • 71