Direct Subprocess result to Tkinter.Listbox widget

0

I need to direct a subprocess that is essentially infinite to a tkinter text/listbox, the Popen output is added to a dictionary, processes and then should be inserted into the listbox however nothing is happening, I can't figure out where I have gone wrong?

The tkinter GUI is created but on Button press it just hangs. I need the process to be non-blocking.

#!/usr/bin/python

from time            import clock, sleep
from os              import system
from collections     import defaultdict
from subprocess      import PIPE, Popen
from threading       import Thread, Lock

import Tkinter as tk
# -------------------------------------------------------------------
#     Global Definitions

mydict ={}   # define the dictionary
dict_lock = Lock()

# ***************************************************************
#
# ************************   Recv App    ************************ 
#
# ***************************************************************
class RecvApp:

    def __init__(self, window):

        self.window = window


        self.RecvList = tk.Listbox(window, height = 10, width = 60)
        self.RecvList.grid(row = 0, columnspan = 11)

        self.RecvButton = tk.Button(window,
                                    text = "Receive",
                                    command = self.RecvBtn_Click)
        self.RecvButton.grid(row = 1)

    def RecvBtn_Click(self):        
        proc = Popen("receivetest -f=/dev/pcan33".split(), stdout = PIPE)
        # This is where I need to write the function for loading info
        payload = proc.stdout.read()
        if payload[0].isdigit():
            splitline = payload.split()
            self.dictadd(splitline)
        self.window.after(1, self.dictadd)        



    def dictAdd(self, info):

        global mydict

        can_ID = info[4]

        p = PCANmsg()

        p.dlc        = int(info[5])
        p.CANtime    = float(info[0])
        p.hdata0     = info[6]  
        p.hdata1     = info[7]
        p.hdata2     = info[8]
        p.hdata3     = info[9]
        p.hdata4     = info[10]
        p.hdata5     = info[11]
        p.hdata6     = info[12]
        p.hdata7     = info[13]
        p.timing     = 1

        if can_ID in mydict.keys():
            q = mydict[can_ID]
            p.COUNT = q.COUNT + 1
            p.PCANperiod = p.CANtime - q.CANtime
        else:
            p.COUNT = 1
            p.PCANperiod = 0.0

        mydict[can_ID] = p

        self.RecvList.insert('%06X: %3d   %02X %02X %02X %02X %02X %02X %02X %02X\t %8.2F %8d ' %
               (int(can_ID,16),
                mydict[can_ID].dlc,
                int(mydict[can_ID].hdata0, 16),
                int(mydict[can_ID].hdata1, 16),
                int(mydict[can_ID].hdata2, 16),
                int(mydict[can_ID].hdata3, 16),
                int(mydict[can_ID].hdata4, 16),
                int(mydict[can_ID].hdata5, 16),
                int(mydict[can_ID].hdata6, 16),
                int(mydict[can_ID].hdata7, 16),
                mydict[can_ID].PCANperiod,
                mydict[can_ID].COUNT)
             )

# ***************************************************************
#
# ************************   PCAM Msg    ************************ 
#
# ***************************************************************
class PCANmsg(object):

  def __init__(self):
    self.dlc        = 0
    self.CANtime    = 0
    self.PCANperiod = 0
    self.COUNT      = 0
    self.hdata0     = 0
    self.hdata1     = 0
    self.hdata2     = 0
    self.hdata3     = 0
    self.hdata4     = 0
    self.hdata5     = 0
    self.hdata6     = 0
    self.hdata7     = 0
    self.timing     = 0

# ***************************************************************
#
# ************************   Print Msg   ************************ 
#
# ***************************************************************

# ***************************************************************
#
# ************************ Print Function *********************** 
#
# ***************************************************************
def PRTdictLoop(locDicLckFLG):

  global mydict

  try:
    count = 0
    while True:
      system("clear")
      print ; print "-" *80  
      with locDicLckFLG:
        for _i in mydict.keys():
          printMsg(mydict, _i)
      print "Keys: ", ;  print mydict.keys()
      print ; print "-" *80  
      count += 1
      print count
      print len(mydict)
      sleep(0.1)
  except KeyboardInterrupt:
    pass

# ***************************************************************
#
# ************************ Script Start  ************************ 
#
# ***************************************************************
if __name__ == "__main__":

    root = tk.Tk()
    myapp = RecvApp(root)
    root.mainloop()
# --------------------------------------------------------------

Sample Data from receivetest:

11961568.703 receivetest: m s 0x0000069e 8 00 1f be 0f 4a 0a 58 1a
11961569.173 receivetest: m s 0x00000663 8 2f 00 62 02 00 56 51 6f
11961569.642 receivetest: m s 0x00000690 8 00 20 03 0f 4a 0a 58 1a
11961606.762 receivetest: m s 0x00000688 8 00 00 00 00 00 00 00 00
11961668.245 receivetest: m s 0x0000069a 8 00 00 00 00 00 56 51 6f
11961668.714 receivetest: m s 0x00000663 8 2f 00 62 02 00 56 51 6f
11961669.183 receivetest: m s 0x0000069e 8 00 1f be 0f 4a 0a 58 1a
11961669.653 receivetest: m s 0x00000690 8 00 20 03 0f 4a 0a 58 1a
11961768.255 receivetest: m s 0x0000069a 8 00 00 00 00 00 56 51 6f
11961768.725 receivetest: m s 0x00000663 8 2f 00 62 02 00 56 51 6f
11961769.194 receivetest: m s 0x0000069e 8 00 1f be 0f 4a 0a 58 1a
11961769.663 receivetest: m s 0x00000690 8 00 20 03 0f 4a 0a 58 1a
11961868.266 receivetest: m s 0x0000069a 8 00 00 00 00 00 56 51 6f
11961868.735 receivetest: m s 0x00000663 8 2f 00 62 02 00 56 51 6f
11961869.205 receivetest: m s 0x0000069e 8 00 1f be 0f 4a 0a 58 1a
11961869.674 receivetest: m s 0x00000690 8 00 20 03 0f 4a 0a 58 1a
11961968.234 receivetest: m s 0x0000069a 8 00 00 00 00 00 56 51 6f
11961968.703 receivetest: m s 0x00000690 8 00 20 03 00 00 56 51 6f
11961969.173 receivetest: m s 0x00000691 8 01 1e 6e 4b 50 5a 06 00
11961969.685 receivetest: m s 0x00000663 8 2f 00 62 02 00 56 51 6f
11961970.154 receivetest: m s 0x0000069e 8 00 1f be 0f 4a 0a 58 1a
python
tkinter
listbox
subprocess
stdout
asked on Stack Overflow Mar 11, 2015 by Jim • edited Mar 11, 2015 by Michael Kazarian

1 Answer

0

See comments in below code. Also you mess dictAdd and dictadd. I replaced all to dictAdd. So, all work for me:

def RecvBtn_Click(self):
    #Here I obtain your sample data. receivetest is text file with data and call "cat ./receivetest" modeling obtain date from your receivetest-command
    proc = Popen("cat ./receivetest".split(), stdout = PIPE)
    # Here fix your code
    payload = proc.stdout.read()
    for line in payload.split('\n'):
        if len(line)> 0 and line[0].isdigit():
            splitline = line.split()
            self.dictAdd(splitline)
        #self.window.after(1, self.dictAdd) #It not work! Use   self.window.after(1, lambda e=None:self.dictAdd(your argument)) instead

def dictAdd(self, info):
    global mydict
    can_ID = info[4]
    p = PCANmsg()
    p.dlc        = int(info[5])
    p.CANtime    = float(info[0])
    p.hdata0     = info[6]  
    p.hdata1     = info[7]
    p.hdata2     = info[8]
    p.hdata3     = info[9]
    p.hdata4     = info[10]
    p.hdata5     = info[11]
    p.hdata6     = info[12]
    p.hdata7     = info[13]
    p.timing     = 1

    if can_ID in mydict.keys():
        q = mydict[can_ID]
        p.COUNT = q.COUNT + 1
        p.PCANperiod = p.CANtime - q.CANtime
    else:
        p.COUNT = 1
        p.PCANperiod = 0.0

    mydict[can_ID] = p
    s = '%06X: %3d   %02X %02X %02X %02X %02X %02X %02X %02X\t %8.2F %8d ' %\
           (int(can_ID,16),
            mydict[can_ID].dlc,
            int(mydict[can_ID].hdata0, 16),
            int(mydict[can_ID].hdata1, 16),
            int(mydict[can_ID].hdata2, 16),
            int(mydict[can_ID].hdata3, 16),
            int(mydict[can_ID].hdata4, 16),
            int(mydict[can_ID].hdata5, 16),
            int(mydict[can_ID].hdata6, 16),
            int(mydict[can_ID].hdata7, 16),
            mydict[can_ID].PCANperiod,
            mydict[can_ID].COUNT)
    self.RecvList.insert("end", s)
    #                    ^^^^  add "end" here

enter image description here UPD: Also I used TableList and python wrapper for it.

answered on Stack Overflow Mar 11, 2015 by Michael Kazarian • edited Mar 11, 2015 by Michael Kazarian

User contributions licensed under CC BY-SA 3.0