Is this a valid way to subclass a python thread to accept a variable update?
Question: I'm looking at the threading module in Python (version 3.4.3), and am having
difficulty finding a way to update a variable in the target function that is
called. I think I could create a global variable to share between the main
program and the thread that I am starting, but found myself creating the
following subclass instead. This seems to work for my purposes, but I'm
curious if this is just a hack or if it's valid.

The goal here is to create a separate thread that regularly (and quietly)
pings a server, and then updates a specified widget with the status of the
update:

    
    
    from tkinter import *
    import threading
    
    class ipthread(threading.Thread):
        def __init__(self, ip=None, labelobj=None):
            self.ip = ip
            threading.Thread.__init__(self, target=self.checkconnection, args=(labelobj,))
    
        def newip(self, ip):
            self.ip = ip
    
        def checkconnection(self, widget):
            while True:
                self.response = os.system("ping -c 1 -W 10 " + self.ip + " > /dev/null 2> /dev/null")
                if self.response==0:
                    widget.config(text="connected", bg='green')
                else:
                    widget.config(text="no connection", bg='red')
                time.sleep(1)
    
    if __name__=="__main__":
        win = Tk()
        status = Label(win, text='')
        status.pack()
        ipchecker = ipthread(ip='192.168.1.1',widget=status)
        time.sleep(10)
        ipchecker.newip('192.168.1.2')
    

While I've put a simple routine here that calls the update after a 10-second
delay, in my program the thread is initialized when I create a tkinter Frame
control panel. The panel has a button that then calls the newip method to
update the thread. It works, so I'm feeling like I've accomplished something,
but is it overkill or unnecessary? I couldn't find another way to initialize
the "checkconnection" routine as a separate thread, and then be able to update
the ip address its using.


Answer: You ask several questions, I'll hopefully answer them all.

**Is this a valid way to pass arguments to a thread?**

There are two ways to pass arguments to a thread:

  * Subclass Thread, redefine the function run and access the new variables from there, as in
    
        class ipthread(threading.Thread):
      def __init__(self, ip=None, labelobj=None):
        self.ip = ip
        self.labelobj = labelobj
    
      def newip(self, ip):
        self.ip = ip
    
      def run(self):
        while True:
            self.response = os.system("ping -c 1 -W 10 " + self.ip + " > /dev/null 2> /dev/null")
            if self.response==0:
                self.labelobj.config(text="connected", bg='green')
            else:
                self.labelobj.config(text="no connection", bg='red')
            time.sleep(1)
    

  * Or you could specify the target to call
    
        def checkconnection(widget, ip):
        while True:
            self.response = os.system("ping -c 1 -W 10 " + self.ip + " > /dev/null 2> /dev/null")
            if self.response==0:
                widget.config(text="connected", bg='green')
            else:
                widget.config(text="no connection", bg='red')
            time.sleep(1)
    
    th = threading.Thread(target=checkconnection, args=(labelobj, ip))
    th.start()
    

**Is this the proper solution for this problem?**

No, it is not!

Widget libraries normally do not like a second thread to cut across their
widgets. You could use a TKInter
[timer](http://stackoverflow.com/a/2401181/1767653) instead of a thread, or
use a [custom event](http://stackoverflow.com/a/276069/1767653) to let the
thread tell the widget that the text has changed.

When using a timer, the GUI becomes unresponsive while the tick is being
handled. In your case, the ping has an unbounded delay so I would keep the
thread and let it send a custom event.

