2010-08-14 10 views
2

Je suis aux prises avec les concepts derrière les sous-processus et les tuyaux, et je travaille avec eux dans un contexte Python. Si quelqu'un pouvait éclaircir ces questions, cela m'aiderait vraiment.Avez-vous réfléchi à l'utilisation de tuyaux et de sous-processus en Python?

  1. Dire que j'ai un pipeline mis en place comme suit

    createText.py | processText.py | cat

    processText.py reçoit des données par stdin, mais comment cela est mis en œuvre? Comment sait-il que plus aucune donnée ne viendra et qu'elle devrait sortir? Je suppose qu'il pourrait chercher un EOF et se terminer en fonction de cela, mais que se passe-t-il si createText.py n'en envoie jamais? Serait-ce considéré comme une erreur sur la partie de createText.py?

  2. Dites parent.py démarre un sous-processus enfant (child.py) et appelle wait() pour attendre la fin de l'enfant. Si parent capture stdout et stderr de l'enfant en tant que tuyaux, est-il toujours possible de les lire après la fin de l'enfant? Ou est-ce que les tuyaux (et les données qu'ils contiennent) sont détruits quand une extrémité se termine?

  3. Le problème général que je veux résoudre est d'écrire un script python qui appelle plusieurs fois rsync avec la classe Popen. Je veux que mon programme attende jusqu'à ce que rsync ait fini, alors je veux vérifier l'état de retour pour voir s'il s'est terminé correctement. Si ce n'est pas le cas, je veux lire le fichier stderr de l'enfant pour voir quelle est l'erreur. Voici ce que j'ai jusqu'à présent

    # makes the rsync call. Will block until the child 
    # process is finished. Returns the exit code for rsync 
    def performRsync(src, dest): 
        print "Pushing " + src + " to " + dest 
        child = Popen(['rsync', '-av', src, dest], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
        child.wait()  
        ## check for success or failure 
        ## 0 is a successful exit code here 
        if not child.returncode: 
         return True 
        else:#ballz 
         stout, sterr = child.communicate() 
         print "ERR pushing " + src + ". " + sterr 
         return False 
    
  4. Mise à jour: J'ai également rencontré ce problème. Tenez compte de ces deux fichiers simples:

    # createText.py 
    for x in range(1000): 
        print "creating line " + str(x) 
        time.sleep(1) 
    
    # processText.py 
    while True: 
        line = sys.stdin.readline() 
        if not line: 
         break; 
        print "I modified " + line 
    

    Pourquoi processText.py dans ce cas ne démarre pas l'impression qu'il obtient des données à partir de stdin? Est-ce qu'un tuyau collecte une quantité de données tamponnées avant de le transmettre?

+0

Si le tuyau est fermé correctement, vous verrez un EOF. Sinon, vous obtiendrez une erreur de tuyau cassée. – Amber

+0

Merci pour le commentaire. Donc, dans l'exemple ci-dessus, quand createText.py se ferme après l'impression d'un texte, est-ce que le simple fait qu'il se termine cause la fermeture de son tube stdout? –

Répondre

1

Cela suppose un environnement UNIXish/POSIXish. EOF dans un pipeline est signalé par aucune donnée à lire, c'est-à-dire read() renvoie une longueur de 0. Cela se produit normalement lorsque le processus de gauche quitte et ferme sa sortie standard. Comme vous ne pouvez pas lire depuis un tube dont l'autre extrémité est fermée, le read dans processText indique EOF.

Si createText ne sortait pas, fermant ainsi sa sortie, il s'agirait d'un programme sans fin qui, dans un pipeline, est une mauvaise chose. Même si ce n'est pas le cas, un programme qui ne se termine jamais habituellement est incorrect (les cas impairs comme yes(1) excepté).

Vous pouvez lire depuis un tube tant que vous n'obtenez pas d'indication EOF ou IOError (errno.EPIPE), ce qui indiquerait également qu'il n'y a plus rien à lire.

Je n'ai pas testé votre code, fait-il quelque chose d'inattendu?