0

I want to repeatedly run a function that retrieves data from an API every 60 seconds. However, I've realized that I can't put it to sleep, or use a while loop, without interrupting the other functions.

My question is, how do I repeatedly retrieve the data from the API/rerun the code that gets the data in the first place, without interrupting the other functions?

Pika Supports Ukraine
  • 3,612
  • 10
  • 26
  • 42
newbie
  • 1
  • 2
  • 1
    Are you creating a real-time dashboard, of sorts? – Robert Harvey Mar 24 '19 at 00:46
  • something like that – newbie Mar 24 '19 at 00:49
  • Well, the answer to your basic question is here: https://stackoverflow.com/q/7168508 – Robert Harvey Mar 24 '19 at 00:50
  • from what i've read from the link you provided, im kind of having a hard time seeing how they've implemented a timer.. – newbie Mar 24 '19 at 01:02
  • They haven't. But you still need a thread. Your requirement was "without interrupting other functions." For timers, look here: https://stackoverflow.com/questions/3393612/run-certain-code-every-n-seconds – Robert Harvey Mar 24 '19 at 01:17
  • With `tkinter`, use the universal widget [`after()`](http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/universal.html) method, which won't interfere with the event-processing loop. You can also use threads, as long as they don't make any `tkinter` related calls (because it doesn't support multithreading). – martineau Mar 24 '19 at 02:09
  • See [this answer](https://stackoverflow.com/a/53697547/355230) for an example of using threads. – martineau Mar 24 '19 at 02:15

1 Answers1

0

below a complete script that retrieve ISS position longitude and latitude from Open Notify and print it on a thread.

I' ve set a 1 second time. You can start and stop the thread. Try now you to add your funcions.

Notice that you have to import this modules

import requests

import json

import tkinter as tk
import threading
import queue
import datetime
import time
import requests
import json

class MyThread(threading.Thread):

    def __init__(self, queue,):
        threading.Thread.__init__(self)

        self.queue = queue
        self.check = True
        
        
    def stop(self):
        self.check = False
        
    def run(self):
        
        while self.check:
            
            response = requests.get("http://api.open-notify.org/iss-now.json")
            data = response.json()
            time.sleep(1)
            self.queue.put(data)
                                    

class App(tk.Frame):
   
    def __init__(self,):
        
        super().__init__()

        self.master.title("Hello World")
        self.master.protocol("WM_DELETE_WINDOW",self.on_close)

        self.queue = queue.Queue()

        self.my_thread = None
    
        self.init_ui()
          
    def init_ui(self):

        self.f = tk.Frame()

        w = tk.Frame()

        tk.Button(w, text="Start", command=self.launch_thread).pack()
        tk.Button(w, text="Stop", command=self.stop_thread).pack()
        tk.Button(w, text="Close", command=self.on_close).pack()

        w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=0)
        self.f.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)

    def launch_thread(self):

        if (threading.active_count()!=0):
            
            self.my_thread = MyThread(self.queue)
            self.my_thread.start()
            self.periodiccall()

    def stop_thread(self):
        if self.my_thread is not None:
            if(threading.active_count()!=1):
                self.my_thread.stop()


    def periodiccall(self):

        self.checkqueue()
        if self.my_thread.is_alive():
            self.after(1, self.periodiccall)
        else:
            pass

    def checkqueue(self):
        while self.queue.qsize():
            try:
                ret = self.queue.get(0)
                print("The ISS is currently over: {0} ".format(ret['iss_position']))
            except queue.Empty:
                pass                    
                   
    def on_close(self):
        if self.my_thread is not None:
            if(threading.active_count()!=1):
                self.my_thread.stop()

        self.master.destroy()
    
if __name__ == '__main__':
    app = App()
    app.mainloop()
Community
  • 1
  • 1
1966bc
  • 1,148
  • 1
  • 6
  • 11