TkInter crashing without error

I’ve been working on a minor python project recently, and went back to my old friend TkInter. TkInter is the standard GUI library for Python. I had used it previously in another small project, so when I wanted to quickly get a GUI going for a project, it made sense to use TkInter. There are many other GUI libraries, but TkInter is supposedly one of the quicker and easier to get going.

TkInter has a number of shortcomings. It’s clunky and not completely intuitive. But the biggest issues that I experience with it is trying to get the interface to update from an outside perspective. My specific implementation required me to update about 20 values on the GUI by reading data from a serial port.

The easiest way to implement this is to make use of the TkInter Label widget. The Label is used for displaying any kind of text. A label can be linked to a TkInter variable, so that if you update the variable, the label automatically gets updated. The difficulty is that you need an event to trigger an update of the variables.

The way to get around this is threads. Python has built in support for threads, via the Threading class. And so you create a thread, and pass it the Tk variables and update them from the thread. This allows you to continue doing other things in the GUI, and still have your thread run. Or does it.

The immediate issue is with how TkInter queues up tasks. Because the label uses Tk variables, you can only update them by calling a set method. Not just by declaring the variable equal to a value. As such this set gets added to a queue. I found that when I clicked a drop down menu (Tk.OptionMenu), my updates would pause. My thread would effectively pause as it waited to be allowed to call the variable set method.

This was not the end of the world, and I probably would have left it like this if I didn’t continue to have the program crash unexpectedly. It would happen often, but at different times, and only when I was interacting with another aspect of the GUI. For example, when I clicked a button or selected a menu item. The program would freeze, causing the python itself to crash, and not reporting any error.

I battled to find much info on this topic. All I’ve been able to come across is the repeating statement that “TkInter is not thread safe” and that you shouldn’t try to access TkInter widgets, except from within the main thread.

There are a couple ways around this. What I ended up using is the TkInter after method. It’s janky. But it works, and has proven reliable. Since I made the change, I have not had my app crashing any more. Now I have a global variable to store the data from serial in. I have a function within my GUI object that updates the Tk variables from the global array. It then calls itself using the after method.

The after method adds a note to TK to do something after a specific amount of time has lapsed, and appears to operate much like an interrupt, ignoring whatever else I am doing and updating on schedule. I first came across the after method as described by Furas on StackOverflow.

Below is a summary of what I was doing before, and what I am doing now.

Before:

class SerialThread(threading.Thread):
  def __init__(self, gui_object):
    threading.Thread.__init__(self)
    self.gui = gui_object

  def run(self):
    #Read serial info
    self.gui.variable1.set(SERIALDATA)

class GUI():
  def __init__(self):
    self.root = tk.Tk()

    self.variable1 = tk.StringVariable(self.root)
    label1 = tk.Label(self.root, textvariable=self.variable1)

    label1.grid(row=1,column=1)

    thread1 = SerialThread(self)
    thread1.start()

 self.root.mainloop()

if __name__ == "__main__":
  GUI();

And after:

TempVariable = "XXXX"
 
class SerialThread(threading.Thread):
  def __init__(self):
    threading.Thread.__init__(self)

  def run(self):
    global TempVariable
    #Read serial info
    TempVariable = SERIALDATA
 
class GUI():
  def __init__(self):
    self.root = tk.Tk()
 
    self.variable1 = tk.StringVariable(self.root)
    label1 = tk.Label(self.root, textvariable=self.variable1)
    label1.grid(row=1,column=1)
 
    self.updateLabels()
 
    thread1 = SerialThread()
    thread1.start()
 
    self.root.mainloop()
 
  def updateLabels(self):
    global TempVariable
    self.variable1.set(TempVariable)
    self.root.after(10,self.updateLabels)
 
if __name__ == "__main__":
  GUI();

UPDATE – below code skips the global variable and uses a thread lock:

class SerialThread(threading.Thread):
  def __init__(self):
    threading.Thread.__init__(self)
    self.serial_data_to_display = ""
    self.lock = threading.Lock()

  def run(self):
    while True:
        with self.lock:
            # serial read stuff
            self.serial_data_to_display = "SERIAL DATA"
        sleep(0.1)

class GUI():
  def __init__(self):
    self.root = tk.Tk()
    self.variable1 = tk.StringVariable(self.root)

    label1 = tk.Label(self.root,  textvariable=self.variable1)
    label1.grid(row=1,column=1)

    self.thread1 = SerialThread()
    self.thread1.start()

    self.root.mainloop()
    self.updateLabels()

  def updateLabels(self):
    with self.thread1.lock:
        self.variable1.set(self.thread1.serial_data_to_display)

    self.root.after(10,self.updateLabels)

if __name__ == "__main__":
  GUI()

Shady Practices (Antera/DomaSchooner Phishing)

I’ve recently gone through the process of moving one of my domains from one domain registrant to another. For a couple reasons, but cost and whois privacy are part of it. I’ve switched hosting providers a number of times, and that’s not an issue, but getting different domain registrants on the same page to ensure a downtime-free transfer isn’t a clear process to me, so during this time I was particularly susceptible to notifications about the transfer.

It was then that I noticed an item in my spam account titled “Domain Expiration SEO”. Now I didn’t notice the SEO in that title at first, and was immediately concerned about the terms “Domain Expiration”. The fact that it was in my spam folder at least made me immediately cautious, but the fact that they used my full name and postal address in the “invoice” confused me.

The email had a large title saying “Final Notice, your account is pending cancellation”, th email came from “info@antera.org”, a domain with no discernable website, and links on the page directed to “domaschooner.win”. What I don’t like is that the entire premise is that you’re about to let something that you had expire. In the meantime nothing could be further from the truth.

It seems they somehow identify domains that are being transferred, grab the whois data and then generate emails, in my opinion, hoping to catch people not paying attention into paying $86 for supposed SEO software.

If you pay close attention to the email, they do note that they “…do not register or renew domain names…” and their email disclaimer states “…This is not a bill or an invoice. This is a SEO purchase offer. You are under no obligation to pay the amount stated unless you accept this purchase offer…”. So while they do a good job of telling the truth, the immediate implication of the email implies something worse. So while probably not illegal, very shady.

Being legal is frustrating

Four years ago I bought a laptop on a student special with the local universities. Pinnacle were the local distributors and the laptop came pre-installed with Windows 7 and Office professional. Wonderful. But it didn’t come with installation DVDs. I queried this with Pinnacle and they said I should use the Lenovo software (OneKey Backup) to create a backup install which would then have everything ready to go. Fine.

A few months later I buy myself an SSD and now want to install Windows on it. Do everything necessary but the 36GB original install complains that my 120GB SSD is too small to install Windows on… So I repartition my original HDD to have an 80GB windows install. Create new backup install, and successfully install on my SSD.

Fast forward to 2016 and for several reasons I haven’t once reformatted my hard drive since original install. But now it’s time. Backup everything I need. Boot up my backup DVD and try and install onto the same SSD. It complains the drive is too small. This is the same drive I installed on four years prior. No other hardware changes have taken place. I spend the next several hours rebooting trying different types of things; use an Ubuntu live CD to format the drive and remove the extra 100MB partition that Windows makes. All efforts are unsuccessful.

I give up and decide to use a legit Windows 7 install DVD I have to just do a plain install. Alas after installation it doesn’t like my key (the one stuck under my laptop), as the DVD is for Windows Ultimate, and my licence is for Windows Premium… Windows used to have their install DVDs freely available through Digital River. But discontinued this service a few years ago. After some extended searching I get hold of an ISO that, after installing, seems legit and is happy with my key. Yay.

I spent more time trying to get an audible.com audio book playing than it took to listen to the book. I have lost every other piece of DRM-locked music I have paid for.

source: https://xkcd.com/488/

But now I don’t have Office. So I begin the same search for an install for Office. I had earlier run a program to extract the CD-Key from my installed software. Again the Digital River ISOs had been discontinued. MS does offer install files for download on their website, but you have to input a valid CD-Key, and the licence for my CD-Key apparently didn’t match any of the versions they had for download. I get hold of some ISOs through different sources, but none of them are playing ball with my CD-Key…

So what eventually happens? I break down and buy Office. Through all my searching, I kept on getting adverts for MS’s Home Use Program. Basically, if your employer has some deal with MS, you can get Office 2016 Pro for like R150. My employer had never advertised this to us (that I recall), but I typed in my work email address and the next day there was an e-mail at work stating that I am eligible. So R150 later I have Office 2016 installed. My biggest gripe (besides having to pay for something I kinda already had) is that it installs everything! Skype for business (which you can’t use a normal Skype account with), MS Access, OneNote and Publisher which I don’t use. There is no option to only install specific software. And no option afterwards to remove some of the software.

But at least I have a working computer again. And I’ve made copies of all the CDs and installs I used. Stuff knows what use the Lenovo OneKey backup DVDs are to be used for.

All of this boils down to DRM, and how difficult it makes people’s lives. Those who try to do the right thing get blocked at every corner. Whereas I could easily have downloaded a cracked copy and be done with all these hassles. Argh!

Logitech K750 – Solar Keyboard

For the past few years, ever since I got a laptop, I’ve used a laptop stand with a built in keyboard, and although a bit limiting as far as manoeuvrability is concerned, it’s worked quite nicely. It allows my screen to be lifted up, and puts it a bit further away from me, while also giving me a full size keyboard to work on.

It’s not an amazing keyboard but it’s done me quite well, until earlier this year when I upended a cup of coffee onto it. To it’s credit, after I stripped it, drained it, and cleaned off as much of the sticky stuff as I could, it continued to work. But the stickiness is still there, impeding my typing. And so I was looking around for keyboards, but couldn’t find one I liked.

logitech

I knew which keyboard I wanted, it was this one (Logitech K750). The solar powered one :) but it was R1,000. And I wasn’t going to pay that much for a keyboard. Ideally I was looking for a wireless ‘island’ key layout, much like my laptop’s keyboard. But I couldn’t find one in I wanted to buy..

And so I resigned myself to sticking to my sticky keyboard. Until Takealot had a daily deal and I picked the same keyboard up for halfprice, much to my delight. In typical Takealot fashion, they completely over-packed the box, but the keyboard itself comes in a slim box, with only the essentials. The keyboard itself is very thin, but with a surprising weight to it. It has some flex to it, and two spindly legs to raise it, but it all seems sturdy enough.

corner

The keyboard has a nice gloss finish (it even comes with a cloth), with the two ‘large’ solar panels taking up space along the top of the keyboard. The keyboard makes use of Logitech’s unifying remote, and even comes with a small extension for plugging in the back of a desktop PC.

The letters on the keys are in the middle or slightly below the centre of the button, which makes it look odd, but obviously has minimal impact. One thing I am missing straight off the bat, is the lack of wrist rest. My laptop obviously has one, and my laptop stand also had a rather sizeable one. But I’m sure the lack of this will be forgotten in time.

A keyboard, below a keyboard, below a keyboard

A keyboard, below a keyboard, below a keyboard

The keyboard has an on/off switch, assumedly to spare a bit of battery and a ‘light testing’ button, which when pressed illuminates a green or red LED depending on how much light the panels are receiving at the time. The keyboard is also designed to never have its battery replaced. Only time will tell, but that’s obviously why we have the solar panels.

Overall a very nice keyboard that I’m happy with. The layout is ever so slightly larger than my old keyboard, so my fingers feel slightly stretched, but I don’t know if that’s actually true or if it’s just the lack of wrist rest that makes me think that. Now I just need to build a new laptop stand for myself.