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)
Répondre
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:
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? –
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? –
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! :) –
Comme nous ne savons pas ce qu'il est que vous faites s'il vous plaît lire https://stackoverflow.com/help/mcve –