2017-07-24 17 views
0

Je crée une interface graphique en utilisant wxPython. Et j'essaye d'afficher les résultats du sous-processus. Ouvrir à TextCtrl une ligne à la fois. Comme il y a une énorme quantité d'informations, la fenêtre subit une phase de NON-RÉPONSE avant de tout afficher. J'utilise aussi des threads. J'ai essayé d'interroger, read(), readline(), itr et toujours la sortie est affichée en une fois au lieu de ligne par ligne après la brève phase PAS RÉPONDANT de la fenêtre. Ce serait génial si quelqu'un pouvait m'aider avec ce problème. Merci!Comment obtenir les résultats de sous-processus stdout et les afficher en temps réel dans TextCtrl? (Python 2.7 - wxPython)

+0

Comme nous ne savons pas ce qu'il est que vous faites s'il vous plaît lire https://stackoverflow.com/help/mcve –

Répondre

0

Si vous utilisez subprocess dans un fil, alors vous avez juste besoin de passer une référence à votre contrôle de texte à ce fil, puis appeler la méthode de contrôle de texte write en utilisant l'une des méthodes thread-safe de wxPython, tels que wx.CallAfter. Voici un exemple assez simple:

import subprocess 
import time 
import wx 

from threading import Thread 


class PingThread(Thread): 

    def __init__(self, text_ctrl): 
     Thread.__init__(self) 
     self.text_ctrl = text_ctrl 
     self.sentinel = True 
     self.start() 

    def run(self):    
     proc = subprocess.Popen("ping www.google.com", 
            shell=True, 
            stdout=subprocess.PIPE) 
     while self.sentinel: 
      line = proc.stdout.readline() 
      if line.strip() == "": 
       pass 
      else: 
       wx.CallAfter(self.text_ctrl.write, line) 

      if not line: break 

     proc.kill() 


class MyFrame(wx.Frame): 

    def __init__(self): 
     wx.Frame.__init__(self, None, title='Redirecter') 
     self.ping_thread = None 

     main_sizer = wx.BoxSizer(wx.VERTICAL) 

     panel = wx.Panel(self) 

     self.log = wx.TextCtrl(panel, style=wx.TE_MULTILINE) 

     ping_btn = wx.Button(panel, label='Ping') 
     ping_btn.Bind(wx.EVT_BUTTON, self.on_ping) 

     main_sizer.Add(self.log, 1, wx.ALL|wx.EXPAND, 5) 
     main_sizer.Add(ping_btn, 0, wx.ALL, 5) 
     panel.SetSizer(main_sizer) 

     self.Bind(wx.EVT_CLOSE, self.on_close) 

     self.Show() 

    def on_ping(self, event): 
     self.ping_thread = PingThread(self.log) 

    def on_close(self, event): 
     if self.ping_thread: 
      self.ping_thread.sentinel = False 
      self.ping_thread.join() 
     self.Destroy() 


if __name__ == '__main__': 
    app = wx.App(False) 
    frame = MyFrame() 
    app.MainLoop() 

Vous pouvez en savoir plus sur wxPython et les discussions sur les liens suivants:

+0

Ceci est un excellent exemple @MikeDriscoll. Le problème de non-réponse est résolu: D. Je me demandais s'il existe un moyen d'afficher stdout en temps réel? –

+0

Cela va être très proche de la réalité en temps réel. Y at-il une raison pour laquelle vous auriez besoin d'être plus rapide que cela? –

+0

Pour une raison quelconque, il montre encore tout à la fois après une longue attente. Je veux juste que l'utilisateur puisse voir la sortie en temps réel car c'est un long processus et ne veut pas qu'ils pensent que rien ne fonctionne. C'est la seule raison pour laquelle je le veux en temps réel. Aussi, merci beaucoup de m'avoir aidé avec la même chose! :) –