1

essentially I am working on a 'draft' of a subscriber counter app in python. I use the YouTube Data API to get the data from YouTube and then loop that piece of code to update the subscriber count. But since the code for my GUI is after the loop it never starts since the loop is infinite and never ends. I tried putting the GUI part before the code to get the sub count but none of the variables are defined so errors are returned. So basically my question is how do I reorganize this so that it works and the sub count gets updated in the GUI. I have heard about people using the threading module but I do not have much experience with this.

import urllib.request
import json
from tkinter import*

name ="pewdiepie"
key = "AIzaSyDAOUFomRB1lxdb_fvSKKaG-FSZDRoVt_s"


i = 1
while i<99999999:
    data = urllib.request.urlopen("https://www.googleapis.com/youtube/v3/channels?part=statistics&forUsername="+name+"&key="+key).read()
    subs = json.loads(data)["items"][0]["statistics"]["subscriberCount"]
    subc =("{:,d}".format(int(subs)))
    print(subc)
    i = i + 1


root = Tk()
root.geometry("900x600")
root.title("Sub Counter")

label1 = Label(text="Sub Count:", font=("Comic Sans MS", 45), fg="Brown").place(x=10, y=20)
label2 = Label(text=subc, font=("Comic Sans MS", 45), fg="Red").place(x=10, y=130)

root.mainloop()
Mihkel
  • 689
  • 7
  • 34
  • Possible duplicate of [How do you run your own code alongside Tkinter's event loop?](https://stackoverflow.com/questions/459083/how-do-you-run-your-own-code-alongside-tkinters-event-loop) – user10455554 Nov 29 '18 at 09:42
  • Take a look at the code in the [answer](https://stackoverflow.com/a/53528140/355230) I posted to a related question. It has a good example. – martineau Nov 29 '18 at 09:53

1 Answers1

3

Threading would solve the problem you're having, but there is an easier solution included with tkinter after(), this answer explains it well:

after(delay_ms, callback=None, *args)

Registers an alarm callback that is called after a given time.

This allows you to call a function after a defined period of time. So, using this we can change your while loop to a function, handing the function the widget we need to update and adding another after() at the end of the function to continue the loop:

def func(label2):
    data = urllib.request.urlopen("https://www.googleapis.com/youtube/v3/channels?part=statistics&forUsername="+name+"&key="+key).read()
    subs = json.loads(data)["items"][0]["statistics"]["subscriberCount"]
    subc =("{:,d}".format(int(subs)))
    label2.config(text=subc)
    label2.update()
    root.after(10, lambda:func(label2))

We then need somewhere to start this from:

func(label2)

With a few other changes to make this work in your program, we end up with the below:

import urllib.request
import json
from tkinter import*

name ="pewdiepie"
key = "AIzaSyDAOUFomRB1lxdb_fvSKKaG-FSZDRoVt_s"


def func(label2):
    data = urllib.request.urlopen("https://www.googleapis.com/youtube/v3/channels?part=statistics&forUsername="+name+"&key="+key).read()
    subs = json.loads(data)["items"][0]["statistics"]["subscriberCount"]
    subc =("{:,d}".format(int(subs)))
    label2.config(text=subc)
    label2.update()
    root.after(10, lambda:func(label2))


root = Tk()
root.geometry("900x600")
root.title("Sub Counter")

label1 = Label(text="Sub Count:", font=("Comic Sans MS", 45), fg="Brown")
label2 = Label(font=("Comic Sans MS", 45), fg="Red")

label1.place(x=10, y=20)
label2.place(x=10, y=130)

func(label2)

root.mainloop()

On a side note, you could optimise this further by using OOP:

import urllib.request
import json
from tkinter import*

class App():
    def __init__(self, root):
        self.root = root
        self.name = "pewdiepie"
        self.key = "AIzaSyDAOUFomRB1lxdb_fvSKKaG-FSZDRoVt_s"
        self.root.geometry("900x600")
        self.root.title("Sub Counter")
        self.label1 = Label(text="Sub Count:", font=("Comic Sans MS", 45), fg="Brown")
        self.label2 = Label(font=("Comic Sans MS", 45), fg="Red")
        self.label1.place(x=10, y=20)
        self.label2.place(x=10, y=130)
        self.root.after(0, self.func)
    def func(self, *args):
        self.data = urllib.request.urlopen("https://www.googleapis.com/youtube/v3/channels?part=statistics&forUsername="+self.name+"&key="+self.key).read()
        self.subs = json.loads(self.data)["items"][0]["statistics"]["subscriberCount"]
        self.subc =("{:,d}".format(int(self.subs)))
        self.label2.config(text=self.subc)
        self.label2.update()
        root.after(10, self.func)

root = Tk()
App(root)
root.mainloop()
Ethan Field
  • 4,646
  • 3
  • 22
  • 43