0

What I'm trying to achieve is quite simple.

So basically, I have a thread that loops continuously, grabbing data from the same url and updating a variable called "data", with text each time. The variable is stored locally within the class.

Then I have a second class which is the mainframe. It should display the latest data, which is determined by whatever the variable in the first class is set to.

The problem is that I cannot find a way to reference that variable from the other class/thread.

The name of the variable that I am setting, and trying to reference is "data".

Here is the source code:

#!/Library/Frameworks/Python.framework/Versions/3.5/bin/python3
# -*- coding: utf-8 -*-

from tkinter import *
import time
import urllib.request
from bs4 import BeautifulSoup
import threading
from queue import Queue

class httpReq(threading.Thread):

    def run(self):

        i = 0
        while 1<5:
            url = "https://twitter.com/realDonaldTrump"
            page = urllib.request.urlopen(url)
            soup = BeautifulSoup(page, "html.parser")
            self.data = data = soup.title.text
            print(x)

x = httpReq()
x.start()

class Example(Frame, httpReq):

    def __init__(self, parent):
        Frame.__init__(self, parent)

        self.parent = parent
        self.initUI()

    def initUI(self):

        self.parent.title("IT Support App")
        self.pack(fill=BOTH, expand=True)

        frame1 = Frame(self)
        frame1.pack(fill=X)

        lbl1 = Label(frame1, text="Primary Video Stream", width= 20)
        lbl1.pack(side=LEFT, padx=5, pady=5)


        lbl6 = Label(frame1, text= x.data)
        lbl6.pack(fill=X, padx=5, expand=True)

        frame2 = Frame(self)
        frame2.pack(fill=BOTH, expand=True)

        lbl2 = Label(frame2, text="Primary Audio Stream", width=20)
        lbl2.pack(side=LEFT, padx=5, pady=5)

        entry2 = Entry(frame2)
        entry2.pack(fill=X, padx=5, expand=True)

        frame3 = Frame(self)
        frame3.pack(fill=BOTH, expand=True)

        lbl3 = Label(frame3, text="Backup Video Stream", width=20)
        lbl3.pack(side=LEFT, padx=5, pady=5)

        entry3 = Entry(frame3)
        entry3.pack(fill=X, pady=5, padx=5, expand=True)

        frame4 = Frame(self)
        frame4.pack(fill=BOTH, expand=True)

        lbl4 = Label(frame4, text="Backup Audio Stream", width=20)
        lbl4.pack(side=LEFT, padx=5, pady=5)

        entry4 = Entry(frame4)
        entry4.pack(fill=X, pady=5, padx=5, expand=True)

        frame5 = Frame(self)
        frame5.pack(fill=X)

        lbl5 = Label(frame5, text="IPTV", width=20)
        lbl5.pack(side=LEFT, padx=5, pady=5)

        entry5 = Entry(frame5)
        entry5.pack(fill=X, pady=5, padx=5, expand=True)

def main():

    root = Tk()
    root.geometry("1920x1080")
    app = Example(root)
    root.mainloop()


if __name__ == '__main__':
    main()
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Couldn't your "Example" class take a second argument to save a reference to the httpReq instance? Then, I guess, you can get hold of your variable. – Frederick Nord Jul 20 '16 at 08:25
  • Thanks Fred. However, I think that's what I have done in the code already. Or am I misunderstanding you? . . . This is the line where I try to do that: class Example(Frame, httpReq): – string theorist Jul 20 '16 at 08:45

2 Answers2

0

Try to declare the data variable outside of the while loop and the run method. Then you can call that static variable using httpReq.data

For reference : Static class variables in Python

SilenT612
  • 43
  • 1
  • 7
  • Thanks. I have tried this. I declare the data variable and set it to "None" outside the first thread. When I run the method however, the frame class only sees the "None" value, not the value that the while loop should change it too. Also, if I declare the variable and set it to none **within** the first thread, but **outside** the while loop, I have the same problem. The mainframe does not see the data variable. – string theorist Jul 20 '16 at 09:01
  • I think I'm getting closer. . . So I just tried declaring the variable within the thread, but outside the class definition. . . Now the mainframe recognizes the "data" attribute of httpReq, but it only sees the value of "None". It seems like either the while loop does not update the data variable, OR the mainframe does not update the value of the variable dynamically? – string theorist Jul 20 '16 at 09:07
  • Are you sure that the while loop executes before the mainframe calls the data attribute ? Because if it is not the case, that's your problem, 'data' never gets updated. – SilenT612 Jul 20 '16 at 09:36
  • Good question! . . I'm not sure. How can i check this? . . The GUI opens up before the "print(x)" line executes, which is the last line of the while loop. I'm not sure if this means that the while loop executes after the mainframe. In any case, I need the mainframe to keep grabbing the 'data' variable continuously as well. Does this mean that i need to crete another loop within the mainframe? – string theorist Jul 20 '16 at 09:57
  • Yes that means that the frame executes before the data variable gets update, that's why it returns none every time. Now for the continuous variable update, maybe this could help http://stackoverflow.com/questions/19233246/python-update-local-variable-in-a-parallel-process-from-parent-program – SilenT612 Jul 20 '16 at 10:03
0

It turns out that there are various ways of doing this. For my purposes however, (since only one thread writes to the variable, and the others read-only) I have found that using a global variable does the job.

First declare and set the variable to none, outside the thread. Then within each thread, declare the variable as global:

#!/Library/Frameworks/Python.framework/Versions/3.5/bin/python3
# -*- coding: utf-8 -*-

from tkinter import *
import time
import urllib.request
from bs4 import BeautifulSoup
import threading
from queue import Queue

data = None

class httpReq(threading.Thread):
    def run(self):

        global data

        while True:
            url = "https://twitter.com/realDonaldTrump"
            page = urllib.request.urlopen(url)
            soup = BeautifulSoup(page, "html.parser")
            data = soup.title.text
            print(data)

x = httpReq()
x.start()

class Example(Frame):

        global data

        def __init__(self, parent):
            Frame.__init__(self, parent)
            self.parent = parent
            self.initUI()

        def initUI(self):
            self.parent.title("Example App")
            self.pack(fill=BOTH, expand=True)

            frame1 = Frame(self)
            frame1.pack(fill=X)

            lbl1 = Label(frame1, text="Title Data:", width= 20)
            lbl1.pack(side=LEFT, padx=5, pady=5)

            lbl2 = Label(frame1, text= data)
            lbl2.pack(fill=X, padx=5, expand=True)

def main():
    root = Tk()
    root.geometry("600x200")
    app = Example(root)
    root.mainloop()

if __name__ == '__main__':
    main()