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 :

Surcharger le fichier "stdout" passé à subprocess.check_call


Sujet :

Python

  1. #1
    Membre confirmé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Points : 455
    Points
    455
    Billets dans le blog
    1
    Par défaut Surcharger le fichier "stdout" passé à subprocess.check_call
    Bonjour,

    J'ouvre un fichier texte en écriture et je le passe en paramètre stdout à subprocess.check_call pour lancer un exécutable et récupérer sa sortie standard.
    Jusque là, rien de bien mystérieux...

    Mes soucis arrivent quand je veux laisser la sortie standard dirigée vers la console, mais la filtrant.

    Voici 2 petits bout de codes, bien plus clairs (dans mon exemple simplifié, je ne veux pas afficher les lignes qui contiennent "11") :
    Ce qui marche
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    with open('foo.txt','wt') as out :
        subprocess.check_call( 'dir' , stdout=out , shell=True )
    for line in open('foo.txt'):
        if '11' not in line :
            print line,
    Ce que je voudrais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class FilteredOutput :
        def write(self,txt):
            if '11' not in txt :
                print txt
    subprocess.check_call( 'dir' , stdout=FilteredOutput() , shell=True )
    Il râle parce que FilteredOutput ne définit pas la méthode fileno.
    En regardant dans le code de subprocess, je vois bien qu'il va directement taper sur un file descriptor et toute la machinerie des fichiers au niveau du système.
    Du coup, ma petite supercherie fait long feu !

    D'où ma question : Existe-t-il un (autre) moyen d'arriver à ce que je veux ?
    Captain'Flam
    anciennement Sopsag, aka Hadrien
    Win seven x64 & Win 10 / Visual 2017 / Python 2.7 / Eclipse

  2. #2
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    J'ai touché un peu ce sujet pour pouvoir afficher en temps réel les lignes sorties d'un programme lancé dans un processus:

    https://www.developpez.net/forums/d1...ole-processus/.

    Dans mes différents essais, j'avais même essayé de détourner l'affichage vers un stringio pour faire une sorte de proxy, mais ça n'a pas marché à cause de fileno.

    J'ai fini par utiliser QProcess de PyQt, qui me permet de faire ce que je veux, mais il ne serait peut-être pas raisonnable d'utiliser cette énorme bibliothèque graphique pour pouvoir utiliser uniquement QProcess .
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par Captain'Flam Voir le message
    D'où ma question : Existe-t-il un (autre) moyen d'arriver à ce que je veux ?
    C'est quoi la question? Créer une s/class du type file qui soit utilisable par .check_call ou filtrer la sortie du sous process avant de l'écrire?
    Dans le second cas, .check_output permet de récupérer la sortie dans une variable qu'on peut filtrer à son gré. Si la sortie est "énorme" et qu'on n'a pas envie d'encombrer la mémoire (avoir à tout filtrer, écrire à la fin), on doit pouvoir écrire Popen(..., stdout=PIPE) et lire le .stdout de l'objet retourné.

    Le temps réel (i.e. supprimer le buffering côté PIPE pour récupérer les données dès qu'elles sont écrites) est encore un autre sujet.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre confirmé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Points : 455
    Points
    455
    Billets dans le blog
    1
    Par défaut
    Bé si !

    En piochant dans les snippets postés dans ton thread, j'ai bricolé ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def execute ( printer,*args,**wargs ):
        p = subprocess.Popen( args,stdout=subprocess.PIPE,**wargs )
        s = p.stdout.readline()
        while len( s ) or p.poll is None :
            printer( s.strip('\n\r\l'))
            s = p.stdout.readline()
     
    def printer ( s ):
        if '11' not in s :
            print '-->',s
    execute( printer,'dir',shell=True )
    Ça fait exactement ce que je veux !
    Merci !
    Captain'Flam
    anciennement Sopsag, aka Hadrien
    Win seven x64 & Win 10 / Visual 2017 / Python 2.7 / Eclipse

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

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