IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Récupérer la sortie du terminal (stdout je crois) dans une GUI ?


Sujet :

Python

  1. #1
    Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 66
    Points : 45
    Points
    45
    Par défaut Récupérer la sortie du terminal (stdout je crois) dans une GUI ?
    Salut à tous !

    Je suis en train de me coder un petit script python avec une GUI en wxPython (mais la GUI n'a aucun intérêt ici, on pourrait aussi bien le faire avec Tkinter, PyQt...).
    Dans ce script, j’exécute une commande externe très longue à exécuter et très bavarde !
    Genre rsync.

    Je voudrais savoir comment faire pour récupérer ce que cette commande affiche dans le terminal au fur et à mesure.
    J'ai testé os.system() et os.popen(), mais tout deux me retourne le résultat une fois l’exécution de la commande terminé !
    Je voudrais pouvoir l'afficher en temps réel, dans une zone de texte par exemple.

    J'ai chercher sur Google, mais j'ai rien trouvé en pur python, que des truc Perl...

    Est-ce que c'est faisable ?

    Merci d'avance !

  2. #2
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut,

    J'ai obtenu ce résultat avec ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
        def get_images(self, rep, bind, r=None):
                reply = subprocess.Popen(["gphoto2", "--get-file", r], 
                                        universal_newlines=True,
                                        stdout=subprocess.PIPE)
     
                while 1:
                    #The two last characters are '\n'
                    text = reply.stdout.readline()[:-2]
                    if type(text) != str or text == '' and reply.poll() != None: 
                        break
                    elif type(text) == str and len(text) > 6:
                        # !!The next two lines are specific for Qt widget
                        bind.appendPlainText(text)
                        QtCore.QCoreApplication.processEvents()
    Donc, en détail, j'utilise gPhoto2 qui importe des photos d'un appareil numérique et je voulais avoir comme toi les progrès dans l'interface de mon appli et pas dans la console.

    Dans les arguments, celui qui t'intéresse est 'bind', il s'agit de l'instance du plainText de mon appli, les deux dernières lignes lui envoient le texte, tu adapteras en fonction de ton widget texte.

    Ce n'est pas non plus garantit avec tout les process, j'ai essayé la même chose avec la librairie dcraw qui est aussi un frontend en ligne de commande et ça ne fonctionne pas.

  3. #3
    Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 66
    Points : 45
    Points
    45
    Par défaut
    Je teste ça dès que j'ai un petit moment et je te tiens au courrant !
    Merci VinsS !

  4. #4
    Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 66
    Points : 45
    Points
    45
    Par défaut
    Voilà, je viens de tester :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import wx
    import subprocess
    import threading
     
    class WorkerTread (threading.Thread):
    	def __init__ (self, window):
    		threading.Thread.__init__(self)
     
    		self.window = window
    		self.start()
     
    	def run (self):
    		self.reply = subprocess.Popen(["ping", "google.com"], universal_newlines=True, stdout=subprocess.PIPE)
    		while True:
    			texte = self.reply.stdout.readline()
    			if type(texte) == str:
    				wx.CallAfter(self.window.textCtrl_append, texte)
     
    	def stop (self):
    		self.reply.kill()
     
    class Gui (wx.Frame):
    	def __init__ (self, titre):
    		self.titre = titre
     
    		wx.Frame.__init__(self, None, wx.ID_ANY, title=self.titre)
    		sizer = wx.GridBagSizer()
     
    		# ----------------------------------------------------------------------------------------------------------- Champ de texte
     
    		self.textCtrl = wx.TextCtrl(self, wx.ID_ANY, size=(800, 600), style=wx.TE_MULTILINE|wx.TE_READONLY)
    		self.textCtrl.SetBackgroundColour('#000000')
    		self.textCtrl.SetForegroundColour('#ffffff')
     
    		sizer.Add(self.textCtrl, (0, 0), flag=wx.EXPAND|wx.ALL, border=10)
     
    		# ----------------------------------------------------------------------------------------------------------- Boutons Quitter...
     
    		buttonExit = wx.Button(self, wx.ID_EXIT)
    		sizer.Add(buttonExit, (1, 0), flag=wx.ALIGN_CENTRE|wx.BOTTOM, border=10)
     
    		# ----------------------------------------------------------------------------------------------------------- Divers
     
    		# Initialisation
    		self.thread = WorkerTread(self)
     
    		# Sizer + Fit
    		self.SetSizerAndFit(sizer)
    		self.Fit()
     
    		# Non redimentionnable
    		self.SetMinSize(self.GetSize())
    		sizer.AddGrowableCol(0)
    		sizer.AddGrowableRow(0)
     
    		# Evénements
    		self.Bind(wx.EVT_BUTTON, self.exit, buttonExit)
     
    	# ----------------------------------------------------------------------------------------------------------- Fonctions Générales
     
    	def textCtrl_append (self, texte):
    		self.textCtrl.AppendText(texte)
     
    	def exit (self, event):
    		self.thread.stop()
    		self.Close()
     
    class Ihm (wx.App):
    	def OnInit (self):
    		root = Gui(u'stdout')
    		root.Show(True)
    		self.SetTopWindow(root)
    		return True
     
    if __name__ == '__main__':
    	app = Ihm()
    	app.MainLoop()
    Ça marche super :


    Petit bémol en revanche.
    Quand je clique su mon bouton "Quitter", l'application ne se ferme pas, je suis obligé de faire "Ctrl+c" dans le terminal.
    Je suppose qu'il faut tuer le subprocess.
    J'ai essayé avec Popen.kill() comme je l'ai vu dans la Doc...
    Mais rien à faire !

    Comment faire ?

    Merci VinsS !

  5. #5
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Euh, ... non, normalement subprocess est mort lorsque sa tâche est terminée.

    Si tu remplace 'self.close()' par 'sys.exit()', ça va pas mieux ?

  6. #6
    Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 66
    Points : 45
    Points
    45
    Par défaut
    Non, toujours pareil !

  7. #7
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Chez moi ça se ferme mais avec une segfault parce que l'affichage du texte est appelé après que la fenêtre soit fermée.

    En modifiant comme ceci, ça résout la question :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
     
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import sys
    import wx
    import subprocess
    import threading
    import time
     
    class WorkerTread (threading.Thread):
        def __init__ (self, window):
            threading.Thread.__init__(self)
     
            self.window = window
            self.is_alive = True
     
        def run (self):
            if self.is_alive:
                self.reply = subprocess.Popen(["ping", "google.com"], 
                                 universal_newlines=True, stdout=subprocess.PIPE)
                while True:
                    texte = self.reply.stdout.readline()
                    if type(texte) == str:
                        wx.CallAfter(self.window.textCtrl_append, texte)
     
     
    class Gui (wx.Frame):
        def __init__ (self, titre):
            self.titre = titre
     
            wx.Frame.__init__(self, None, wx.ID_ANY, title=self.titre)
            sizer = wx.GridBagSizer()
     
            # ---------------Champ de texte
     
            self.textCtrl = wx.TextCtrl(self, wx.ID_ANY, size=(800, 600),
                                       style=wx.TE_MULTILINE|wx.TE_READONLY)
            self.textCtrl.SetBackgroundColour('#000000')
            self.textCtrl.SetForegroundColour('#ffffff')
     
            sizer.Add(self.textCtrl, (0, 0), flag=wx.EXPAND|wx.ALL, border=10)
     
            # ------------- Boutons Quitter...
     
            buttonExit = wx.Button(self, wx.ID_EXIT)
            sizer.Add(buttonExit, (1, 0), flag=wx.ALIGN_CENTRE|wx.BOTTOM, border=10)
     
            # ------Divers
     
            # Initialisation
            self.thread = WorkerTread(self)
            self.thread.start()
     
            # Sizer + Fit
            self.SetSizerAndFit(sizer)
            self.Fit()
     
            # Non redimentionnable
            self.SetMinSize(self.GetSize())
            sizer.AddGrowableCol(0)
            sizer.AddGrowableRow(0)
     
            # Evénements
            self.Bind(wx.EVT_BUTTON, self.exit, buttonExit)
     
            # -------Fonctions Générales
     
        def textCtrl_append (self, texte):
            self.textCtrl.AppendText(texte)
     
        def exit (self, event):
            self.thread.is_alive = False
            time.sleep(0.1)
            self.Close()
     
    class Ihm (wx.App):
        def OnInit (self):
            root = Gui(u'stdout')
            root.Show(True)
            self.SetTopWindow(root)
            return True
     
    if __name__ == '__main__':
        app = Ihm()
        app.MainLoop()
    Il y a encore un message en console après fermeture :

    Exception TypeError: "'bool' object is not callable" in <module 'threading' from '/usr/lib/python2.6/threading.pyc'> ignored
    Pas la moindre idée d'où cela peut provenir. Mais comme ça se termine par 'ignored' ...

  8. #8
    Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 66
    Points : 45
    Points
    45
    Par défaut
    Si, hier en me brossant les dents j'ai eu une illumination !
    J'ai une boucle infinie dans mon thread.
    Même si je kill le subprocess, elle tourne toujours.

    Donc voilà.
    J'ai pas le temps là, mais je sais d'où ça viens.
    Je doit stopper ma boucle infinie et killer le subprocess.

    Merci !

  9. #9
    Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 66
    Points : 45
    Points
    45
    Par défaut
    C'était bien la boucle infinie.
    Maintenant tout marche, sans os.kill(), sys.exit()...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import wx
    import subprocess
    import threading
     
    class WorkerTread (threading.Thread):
    	def __init__ (self, window):
    		threading.Thread.__init__(self)
     
    		self.window = window
    		self.statut = False
     
    		self.start()
     
    	def run (self):
    		self.reply = subprocess.Popen(["ping", "google.com"], universal_newlines=True, stdout=subprocess.PIPE)
    		while True:
    			if self.statut:
    				break
    			if not self.reply.poll():
    				texte = self.reply.stdout.readline()
    				if type(texte) == str:
    					wx.CallAfter(self.window.textCtrl_append, texte)
     
    	def stop (self):
    		self.statut = True
    		self.reply.kill()
     
    class Gui (wx.Frame):
    	def __init__ (self, titre):
    		self.titre = titre
     
    		wx.Frame.__init__(self, None, wx.ID_ANY, title=self.titre)
    		sizer = wx.GridBagSizer()
     
    		# ----------------------------------------------------------------------------------------------------------- Champ de texte
     
    		self.textCtrl = wx.TextCtrl(self, wx.ID_ANY, size=(800, 600), style=wx.TE_MULTILINE|wx.TE_READONLY)
    		self.textCtrl.SetBackgroundColour('#000000')
    		self.textCtrl.SetForegroundColour('#ffffff')
     
    		sizer.Add(self.textCtrl, (0, 0), flag=wx.EXPAND|wx.ALL, border=10)
     
    		# ----------------------------------------------------------------------------------------------------------- Boutons Quitter...
     
    		buttonExit = wx.Button(self, wx.ID_EXIT)
    		sizer.Add(buttonExit, (1, 0), flag=wx.ALIGN_CENTRE|wx.BOTTOM, border=10)
     
    		# ----------------------------------------------------------------------------------------------------------- Divers
     
    		# Initialisation
    		self.thread = WorkerTread(self)
     
    		# Sizer + Fit
    		self.SetSizerAndFit(sizer)
    		self.Fit()
     
    		# Non redimentionnable
    		self.SetMinSize(self.GetSize())
    		sizer.AddGrowableCol(0)
    		sizer.AddGrowableRow(0)
     
    		# Evénements
    		self.Bind(wx.EVT_BUTTON, self.exit, buttonExit)
     
    	# ----------------------------------------------------------------------------------------------------------- Fonctions Générales
     
    	def textCtrl_append (self, texte):
    		self.textCtrl.AppendText(texte)
     
    	def exit (self, event):
    		self.thread.stop()
    		self.Close()
     
    class Ihm (wx.App):
    	def OnInit (self):
    		root = Gui(u'stdout')
    		root.Show(True)
    		self.SetTopWindow(root)
    		return True
     
    if __name__ == '__main__':
    	app = Ihm()
    	app.MainLoop()
    Merci beaucoup pour ton aide VinsS !

  10. #10
    Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 66
    Points : 45
    Points
    45
    Par défaut
    Encore un peu plus propre/optimisé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import wx
    import subprocess
    import threading
    import sys
     
    class WorkerTread (threading.Thread):
    	def __init__ (self, window):
    		self.window = window
     
    		threading.Thread.__init__(self)
    		self.start()
     
    	def run (self):
    		self.reply = subprocess.Popen(["ping", "google.com"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     
    		ligne = self.reply.stdout.readline()
    		while ligne:
    			wx.CallAfter(self.window.textCtrl_append, ligne)
    			sys.stdout.flush()
    			ligne = self.reply.stdout.readline()
     
    	def stop (self):
    		self.reply.kill()
     
    class Gui (wx.Frame):
    	def __init__ (self, titre):
    		self.titre = titre
     
    		wx.Frame.__init__(self, None, wx.ID_ANY, title=self.titre)
    		sizer = wx.GridBagSizer()
     
    		# ----------------------------------------------------------------------------------------------------------- Champ de texte
     
    		self.textCtrl = wx.TextCtrl(self, wx.ID_ANY, size=(800, 600), style=wx.TE_MULTILINE|wx.TE_READONLY)
    		self.textCtrl.SetBackgroundColour('#000000')
    		self.textCtrl.SetForegroundColour('#ffffff')
     
    		sizer.Add(self.textCtrl, (0, 0), flag=wx.EXPAND|wx.ALL, border=10)
     
    		# ----------------------------------------------------------------------------------------------------------- Boutons Quitter...
     
    		buttonExit = wx.Button(self, wx.ID_EXIT)
    		sizer.Add(buttonExit, (1, 0), flag=wx.ALIGN_CENTRE|wx.BOTTOM, border=10)
     
    		# ----------------------------------------------------------------------------------------------------------- Divers
     
    		# Initialisation
    		self.thread = WorkerTread(self)
     
    		# Sizer + Fit
    		self.SetSizerAndFit(sizer)
    		self.Fit()
     
    		# Non redimentionnable
    		self.SetMinSize(self.GetSize())
    		sizer.AddGrowableCol(0)
    		sizer.AddGrowableRow(0)
     
    		# Evénements
    		self.Bind(wx.EVT_BUTTON, self.exit, buttonExit)
    		self.Bind(wx.EVT_CLOSE, self.post_exit)
     
    	# ----------------------------------------------------------------------------------------------------------- Fonctions Générales
     
    	def textCtrl_append (self, texte):
    		self.textCtrl.AppendText(texte)
     
    	def post_exit (self, event):
    		self.thread.stop()
    		self.Destroy()
     
    	def exit (self, event):
    		self.Close()
     
    class Ihm (wx.App):
    	def OnInit (self):
    		root = Gui(u'stdout')
    		root.Show(True)
    		self.SetTopWindow(root)
    		return True
     
    if __name__ == '__main__':
    	app = Ihm()
    	app.MainLoop()
    Mais comme tu m'as dis VinsS, ça ne marche pas tout le temps !
    J'ai essayé de remplacer le ping par la commande "tree" (Linux), ça n'affiche rien, et ça bloque la fermeture du programme.

  11. #11
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Mais tu as toujours ta ligne reply.kill() et tes fonctions stop () et post_exit() qui ne servent à rien.

    Je pensais aussi que tu voulais vraiment pinger plusieurs fois de suite.

    Alors on peut simplifier tout ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import sys
    import wx
    import subprocess
    import threading
    import time
     
    class WorkerTread (threading.Thread):
        def __init__ (self, window):
            threading.Thread.__init__(self)
     
            self.window = window
     
        def run (self):
            reply = subprocess.Popen(["ping", "google.com"], universal_newlines=True,
                                            stdout=subprocess.PIPE)
            while True:
                texte = reply.stdout.readline()
                if type(texte) == str:
                    wx.CallAfter(self.window.textCtrl_append, texte)
                    break
     
     
    class Gui (wx.Frame):
        def __init__ (self, titre):
            self.titre = titre
     
            wx.Frame.__init__(self, None, wx.ID_ANY, title=self.titre)
            sizer = wx.GridBagSizer()
     
            # ---------------Champ de texte
     
            self.textCtrl = wx.TextCtrl(self, wx.ID_ANY, size=(800, 600), 
                                                 style=wx.TE_MULTILINE|wx.TE_READONLY)
            self.textCtrl.SetBackgroundColour('#000000')
            self.textCtrl.SetForegroundColour('#ffffff')
     
            sizer.Add(self.textCtrl, (0, 0), flag=wx.EXPAND|wx.ALL, border=10)
     
            # ------------- Boutons Quitter...
     
            buttonExit = wx.Button(self, wx.ID_EXIT)
            sizer.Add(buttonExit, (1, 0), flag=wx.ALIGN_CENTRE|wx.BOTTOM, border=10)
     
            # ------Divers
     
            # Initialisation
            self.thread = WorkerTread(self)
            self.thread.start()
     
            # Sizer + Fit
            self.SetSizerAndFit(sizer)
            self.Fit()
     
            # Non redimentionnable
            self.SetMinSize(self.GetSize())
            sizer.AddGrowableCol(0)
            sizer.AddGrowableRow(0)
     
            # Evénements
            self.Bind(wx.EVT_BUTTON, self.close, buttonExit)
     
            # -------Fonctions Générales
     
        def textCtrl_append (self, texte):
            self.textCtrl.AppendText(texte)
     
        def close(self, event):
            self.Close()
     
    class Ihm (wx.App):
        def OnInit (self):
            root = Gui(u'stdout')
            root.Show(True)
            self.SetTopWindow(root)
            return True
     
    if __name__ == '__main__':
        app = Ihm()
        app.MainLoop()
    Comme ça, ce sera plus propre.

  12. #12
    Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 66
    Points : 45
    Points
    45
    Par défaut
    La commande ping n'est qu'un exemple.
    Je pense plutôt m'en servir avec rsync...

    Mais quand ça défile trop vite ça ne marche plus !
    J'essaye de trouve quelque chose d'autre.

  13. #13
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Qu'est ce qui défile ?

    C'est mon dernier code que tu as essayé ?

    Je suis sous GNU/Linux avec python 2.6 et tout fonctionne parfaitement.

  14. #14
    Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 66
    Points : 45
    Points
    45
    Par défaut
    Je suis également sous linux et python 2.6.6.
    J'essaye de faire avec ['tree', '/usr/'] en argument...
    Et là rien ne s'affiche et ça bloque.
    Je pense que ça va trop vite.

  15. #15
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Ma question reste posée : c'est mon dernier code que tu testes là ?

  16. #16
    Membre actif
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 159
    Points : 224
    Points
    224
    Par défaut
    Salut,
    Chez moi (python 2.6 on Gnu/Linux), le code de VinsS n'affiche que la première ligne.
    Pour que toutes les lignes soient affichées au fur et à mesure, j'ai modifié la fonction WorkerTread.run() pour qu'elle ressemble à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    def run (self):
            reply = subprocess.Popen(["ping", "google.com"], universal_newlines=True,
                                            stdout=subprocess.PIPE)
            texte = True
            while texte:
                texte = reply.stdout.readline()
                wx.CallAfter(self.window.textCtrl_append, texte)
    Ceci marche très bien chez moi, y compris avec des commandes du genre ['ls', '-la', '/']

  17. #17
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Citation Envoyé par valAa Voir le message
    Salut,
    Chez moi (python 2.6 on Gnu/Linux), le code de VinsS n'affiche que la première ligne.
    Pour que toutes les lignes soient affichées au fur et à mesure, ...
    Mais ce sont toujours les mêmes lignes, le ping se repète et ce n'était pas désiré.

    C'est parce que je pensais que c'était voulu que j'avais introduit une condition au thread.

    Le thread lui-même n'est pas nécessaire pour un simple ping, mais ce code est censé faire des choses plus laborieuses sinon plus longues.

  18. #18
    Membre du Club
    Inscrit en
    Novembre 2007
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 66
    Points : 45
    Points
    45
    Par défaut
    Non, ce n'est pas ton dernier code, mais même avec le dernier, si j’enlève le break, c'est pareil (je parle pour le tree, le ping marche niquel).
    Le ping c'est juste pour voir que ça marche bien, et que le thread n'est pas mort.
    C'est voulu que les lignes ce succède.

    Je voudrais pouvoir arriver à afficher la sortie de n'importe qu'elle commande en direct, quelque soit ça longueur d'exécution, ou sa verbosité.

    Le ping est lent, donc ça passe, mais des application comme tree (sudo apt-get install tree) et quelque chose de très rapide, peut être plus que la boucle...
    Donc voilà, dilem !

    Je cherche comment faire, mais en vain.

    Merci quand même à vous deux, vous m'avez bien aidé jusque là !

  19. #19
    Membre actif
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 159
    Points : 224
    Points
    224
    Par défaut
    Avec tree , j'ai l'impression que le problème est que ton thread bouffe 100% du cpu (tree c'est gourmand). Du coup l'affichage se fait en bloc (une bonne trentaine de secondes chez moi avant l'arrivée des premières lignes sur un tree /usr/
    Je ne sais pas ce que tu appelles "en direct", mais une solution à la rache (TM) pourrait-être de rajouter un time.sleep(0.01) par exemple dans ta boucle while, pour laisser l'affichage se faire correctement à chaque tour.
    Par contre je sais pas si c'est très propre comme méthode (c'est une vraie question, je suis pas un pro des threads). Si c'est pas propre j'accepte les coups

  20. #20
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Je viens de tester avec tree, je comprend mieux ce que tu veux dire.

    L'affichage ne se fait qu'une fois le process terminé et ça peut être particulièrement long.

    D'après moi, subprocess et la manière dont tu t'en sers ne sont pas en cause, je ne connait pas du tout wxpython, mais je ne serais pas étonné que, pour des raisons de rendement, l'affichage des widgets et dans les widgets ne soit mit à jour qu'une fois revenu dans la boucle principale du programme.

    C'est, par exemple, le cas avec Qt, si tu regardes mon tout premier exemple de code, tu verra la ligne :

    QtCore.QCoreApplication.processEvents()
    c'est elle qui force la mise à jour du texte, sans quoi tout s'afficherait à la fin du travail, ce qui n'est pas le but recherché.

    wxpython n'a pas ce type d'instruction ? Je serais étonné.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [Débutant] Récupérer les coordonnées d'un ensemble de pixels dans une matrice
    Par reda24 dans le forum Images
    Réponses: 5
    Dernier message: 01/06/2007, 18h06
  2. récupérer le nom du serveur et l'afficher dans une jsp
    Par barouz dans le forum Servlets/JSP
    Réponses: 21
    Dernier message: 19/04/2007, 15h32
  3. Recherche croisé dans une base de donnée
    Par elephant13 dans le forum C#
    Réponses: 1
    Dernier message: 24/03/2007, 15h26
  4. Réponses: 1
    Dernier message: 31/07/2006, 13h54
  5. Réponses: 1
    Dernier message: 05/05/2006, 14h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo