Redirect sys.stdout from ping results to a wx.TextCtrl widget

Question:

I’m trying to redirect the sys.stdout stream to a wx.TextCtrl widget. In this code, i used ping but how to redirect results to wx.textctrl or statictext widgets. I can send variable from my input to wx.statictext but not able to get the stdout from ping results. hope someone here can help.

I’m using python 3.6.0 with wx 2.8.12.1

import wx
import os


class RandomPanel(wx.Panel):

    def __init__(self, parent, color):

        wx.Panel.__init__(self, parent)
        self.SetBackgroundColour(color)



class MainPanel(wx.Panel):

    def __init__(self, parent):

        wx.Panel.__init__(self, parent)

        topSplitter = wx.SplitterWindow(self)
        vSplitter = wx.SplitterWindow(topSplitter)

        panelOne = RandomPanel(vSplitter, "white")


        self.txt = wx.TextCtrl(panelOne, 
                    style=wx.TE_PROCESS_ENTER, 
                    pos=(7, 8), size=(330, 30))
        self.txt.SetFocus()
        self.txt.Bind(wx.EVT_TEXT_ENTER, self.ping)

        panelTwo = RandomPanel(vSplitter, "white")
        vSplitter.SplitVertically(panelOne, panelTwo)
        vSplitter.SetSashGravity(0.5)

        panelThree = RandomPanel(topSplitter, "black")
        topSplitter.SplitHorizontally(vSplitter, panelThree)
        topSplitter.SetSashGravity(0.5)
        self.term = wx.StaticText(panelThree, -1, '', pos=(6, 100))
        self.term.SetForegroundColour((255, 255, 255))  #set font color
        self.term.SetBackgroundColour((0, 0, 0)) #set background color

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(topSplitter, 1, wx.EXPAND)
        self.SetSizer(sizer)

    def ping(self, event):
        put = self.txt.GetValue()
        self.p = os.system("ping -n 1 "+put)
        self.term.SetLabel(put)
        self.p.AppendText('>>> ')
        self.p.AppendText(event)



class MainFrame(wx.Frame):

    def __init__(self):
           wx.Frame.__init__(self, None, title="ping tool",
                          size=(800, 600))
        panel = MainPanel(self)
        self.Show()



if __name__ == "__main__":
    app = wx.App(False)
    frame = MainFrame()
    app.MainLoop()
Asked By: Alfred George

||

Answers:

Replace import os with from subprocess import call, Popen, PIPE, STDOUT
Then replace

self.p = os.system("ping -n 1 "+put)
self.term.SetLabel(put)
self.p.AppendText('>>> ')
self.p.AppendText(event)

with

comm = Popen(['ping',put],stdout=PIPE,stderr=STDOUT,universal_newlines=True)
for i in iter(comm.stdout.readline, b''):
    if i != '': pass
    else: break
    self.term.SetLabel(str(i))
    wx.Yield()

This will read the output from the ping command, output it and then call Yield to allow the wx.App() mainloop to update the screen from within the for loop

You will probably want to put a stop mechanism in there at some point.

Edit:
To create a set of rolling results, I would change self.term from a StaticText to a TextCtrl

self.term = wx.TextCtrl(panelThree, -1, '',size=(400,200),style=wx.TE_MULTILINE)

and then in the ping routine change SetLabel to AppendText

def ping(self, event):
    put = self.txt.GetValue()
    comm = Popen(['ping',put],stdout=PIPE,stderr=STDOUT,universal_newlines=True)
    for i in iter(comm.stdout.readline, b''):
        if i != '': pass
        else: break
        self.term.AppendText(str(i))
        wx.Yield()
Answered By: Rolf of Saxony

@Rolf of Saxony, i have updated the code thanks for your help.

def ping(self, event):
        a = []
        put = self.txt.GetValue()
        comm = Popen(['ping', put], stdout=PIPE, stderr=STDOUT, universal_newlines=True)
        for i in iter(comm.stdout.readline, b''):
            if i != '':
                pass
            else:
                break
            a.append(str(i))
            self.term.SetLabelText("start pinging......")
        self.term.SetLabelText("n".join(a))
        wx.Yield()
Answered By: Alfred George

How about if I want to ping many IPs in the same time and print it in the widget?

Answered By: Phatnv
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.