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 :

Exécuter puis récupérer la sortie d'un script Python en temps réel et non en un seul bloc


Sujet :

Python

  1. #1
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut Exécuter puis récupérer la sortie d'un script Python en temps réel et non en un seul bloc
    Bonjour,
    voici un script tout bête nommé test.py :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #!/usr/bin/env python
    #coding=utf-8
    import time
    for i in range (1,5):   
        print i
        time.sleep(3)
    Je veux le lancer et récupérer les lignes écrites par le script comme dans une console classique ligne par ligne. J'ai le code suivant mais il traite la sortie en un seul bloc et non en temps réel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/usr/bin/env python
    #coding=utf-8
    import os
     
    import subprocess
    fileToTest = 'cheminCompletDuScriptCiDessus'
     
    os.chdir(os.path.dirname(fileToTest))
    x = subprocess.Popen( ["python.exe", fileToTest],
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE )
    print x.stdout.read()
    Comment modifier ce code pour obtenir l'affichage des lignes en temps réel ?

    Toute info. est la bienvenue.

    PS : ce post a été impulsé par la lecture de cet autre.

  2. #2
    Futur Membre du Club
    Inscrit en
    Juillet 2009
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 4
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par rambc Voir le message
    Bonjour,
    voici un script tout bête nommé test.py :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #!/usr/bin/env python
    #coding=utf-8
    import time
    for i in range (1,5):   
        print i
        time.sleep(3)
    Je veux le lancer et récupérer les lignes écrites par le script comme dans une console classique ligne par ligne. J'ai le code suivant mais il traite la sortie en un seul bloc et non en temps réel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/usr/bin/env python
    #coding=utf-8
    import os
     
    import subprocess
    fileToTest = 'cheminCompletDuScriptCiDessus'
     
    os.chdir(os.path.dirname(fileToTest))
    x = subprocess.Popen( ["python.exe", fileToTest],
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE )
    print x.stdout.read()
    Comment modifier ce code pour obtenir l'affichage des lignes en temps réel ?

    Toute info. est la bienvenue.

    PS : ce post a été impulsé par la lecture de cet autre.
    À mon avis, "print x.stdout.read()" écrit le contenu de stdout au moment de l'execution de la ligne...
    Tu devrais répeter plusieurs fois l'instruction:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ...
    while machintruc:
         print x.stdout.read()
    mais ça écrirait plusieurs fois la sortie... il faudrait en fait faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ...
    while machintruc:
         print la dernière ligne de x.stdout.read()

  3. #3
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Ta méthode n'a pas de sens il me semble. C'est la façon dont on appelle la commande subprocess qui pose problème.

    Au pire, existe-t-il un autre moyen de faire ce que je souhaite ?

  4. #4
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Non, la manière dont tu te sers de Popen est correcte.
    Il te suffit maintenant de faire un select sur les sorties, et de ne lire que quelques caractères à la fois depuis ces sorties.
    Un appel à read sans paramètre tente d'atteindre eof avant de retourner le résultat.

  5. #5
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Mon souci n'est pas d'afficher ligne par ligne la sortie mais bien de récupérer en temps réel et non pas une fois le fichier script.py complétèment éxécuté. Peut-être faut-il regardé du côté des thread ? Peut-être qu'on ne pense pas à la même chose.

  6. #6
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Relis ce que j'ai dit et tu verras que je n'ai nulle part parlé de ligne.

    Sinon, tu peux rediriger directement la sortie du processus vers stdout.

  7. #7
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Dans ce cas, éclaires moi de ton savoir car là je sèche totalement...

  8. #8
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Ce que veut dire Antoine_935 c'est que ton soucis de récupérer tes données en "temps réel" et ton utilisation de read sans argument sont incompatibles.

    Un read sans argument (qui est le nombre max d'octets à lire, sauf à trouver EOF avant) signifie que tu demandes à lire jusqu'à la fin de fichier (voir doc Python). Ici, ta "fin de fichier" c'est quand le côté écriture du pipe est fermé et cela arrive après le dernier sleep(3) pour i valant 4.

    Avec ton exemple "test.py", c'est bien des lignes que tu écris (print i). Remplace ton
    par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    line = x.stdout.readline()
    while line:
       print line
       sys.stdout.flush()
       line = x.stdout.readline()
    Remarque le "sys.stdout.flush" pour être sur que l'affichage se fasse en temps réel.
    De façon analogue, dans ton "test.py", fais suivre le "print i" par "sys.stdout.flush()" pour que i soit, à ce moment là, réellement écrit dans le pipe (sinon, ça bufferise et ça n'écrit que quand le buffer est plein ou, ici, quand tu sors de la boucle (peu de données))

    Là, on utilise readline parce qu'à chaque itération, c'est bien une ligne qui est écrite dans le pipe. Si c'était des données quelconques, tu devrais utiliser un read en précisant la taille (si tu la connais) ou, sinon, faire une succession de read(1) pour ne rien rater.
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  9. #9
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Merci beaucoup plxpy pour ces lignes. Pour avoir le bon résultat, il faut aussi la bonne commande. Et là, merci UliPad. Voici le code complet.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import sys, subprocess
     
    x = subprocess.Popen( ["python.exe", "-u", "script.py"],
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE )
     
    line = x.stdout.readline()
    while line:
       print line
       sys.stdout.flush()
       line = x.stdout.readline()

  10. #10
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    N'oublie pas stderr dans tout ça.
    La seule solution pour considérer les deux, c'est le select.

  11. #11
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Antoine_935, j'ai juste mis ce snippet en partant du principe qu'il n'y a pas d'erreur car le souci était ailleurs de mon point de vue.

    Après je suis d'accord qu'il faudra être plus propre et gérer les cas où l'éxécution ne fonctionne pas.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 26/08/2010, 09h53
  2. Réponses: 15
    Dernier message: 15/06/2009, 17h35
  3. Réponses: 7
    Dernier message: 05/04/2007, 16h15
  4. Réponses: 5
    Dernier message: 16/03/2007, 12h16

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