Comment faire pour exécuter plusieurs commandes de façon synchrone à partir d'un sous-processus.Popen commande?
Est-il possible d'exécuter un nombre arbitraire de commandes en séquence à l'aide de la même sous-processus de commande?
J'ai besoin de chaque commande à attendre pour la précédente à remplir avant d'exécuter et j'ai besoin de tous pour être exécutées dans la même session/shell. J'ai aussi besoin de ce travail dans la version 2.6 de Python, Python 3.5. J'ai aussi besoin de la sous-processus de commande sous Linux, Windows et macOS (c'est pourquoi je suis juste en utilisant echo
commandes comme exemples ici).
Voir non-travail code ci-dessous:
import sys
import subprocess
cmds = ['echo start', 'echo mid', 'echo end']
p = subprocess.Popen(cmd=tuple([item for item in cmds]),
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in iter(p.stdout.readline, b''):
sys.stdout.flush()
print(">>> " + line.rstrip())
Si ce n'est pas possible, quelle approche doit-je prendre pour l'exécution de mes commandes de synchronisation de séquence dans la même session/shell?
Comment sur l'exécution de cmd1, cmd2, cmd3 en exécution séparée de Popen?
J'ai édité ma question car il implique un nombre arbitraire de commandes.
si j'exécute un Popen par cmd, ils seront exécutés dans leurs propres séances. J'ai besoin de tous pour être exécutées dans la même session. Je suis en train de modifier ma question d'inclure cette info maintenant.
Double Possible de l'exécution de plusieurs commandes bash avec des sous-processus
OriginalL'auteur fredrik | 2016-09-27
Vous devez vous connecter pour publier un commentaire.
Si vous voulez exécuter plusieurs commandes l'une après l'autre dans le même session/shell, vous devez lancer un interpréteur de commandes et de le nourrir avec toutes les commandes, un à la fois, suivie par une nouvelle ligne, et fermer le tuyau à la fin. Il a de sens que si certaines commandes ne sont pas de vrais processus, mais des commandes shell qui pourrait par exemple changer le shell de l'environnement.
Exemple à l'aide de Python 2.7 sous Windows:
Pour avoir ce code s'exécuter sous Linux, vous devez remplacer
cmd.exe
avec/bin/bash
et probablement changer l'encodage utf8.Pour Python 3, vous devez encoder les commandes et probablement décoder leur sortie, et à utiliser des parenthèses avec imprimer.
Attention: ceci ne peut fonctionner que pour peu de sortie. S'il y avait suffisamment de puissance pour remplir le canal de la mémoire tampon avant de fermer le stdin de la pipe, ce code de blocage. D'une façon plus robuste serait d'avoir un deuxième thread pour lire la sortie des commandes pour éviter ce problème.
OriginalL'auteur Serge Ballesta
Une solution possible, ressemble à son cours d'exécution dans la même coquille:
Remarque - Si vous passez votre commande comme une chaîne de caractères, puis la coquille doit être Vrai
Remarque: Cela fonctionne sous linux, vous pouvez trouver quelque chose de similaire sur windows.
Espère que ça va aider.
De python doc -
Oui, l'utilisation de shell=True n'est pas une façon préférable
Apparemment, au moins dans python 2.7 celui-ci fonctionne également sur windows: >Windows shell=True, la variable d'environnement COMSPEC spécifie le shell par défaut. Le seul moment où vous devez spécifier shell=True sur Windows, c'est quand la commande que vous souhaitez exécuter est intégré dans le shell (par exemple, dir ou copie). Vous n'avez pas besoin de shell=True pour exécuter un fichier de commandes ou de la console executable.<
tous les au-dessus de 3 commandes dump leur sortie sur
STDOUT
en mode sérialisé ou il y a une possibilité d'obtenir un fatras de sortie.Bien que shell=True n'est pas préférable de documentation, dans certains cas particuliers (par exemple, si vous voulez exécuter la commande git push de jupyter portable avec un non-clé par défaut), cela s'avère être la seule solution. Donc un grand MERCI à VOUS, @AlokThakur.
OriginalL'auteur AlokThakur
Ceci est similaire à la réponse posté par Serge Ballesta, mais pas tout à fait. Utiliser pour son exécution asynchrone, où vous n'avez pas de soins sur les résultats. Utiliser le mien pour le traitement et le résultat de la cueillette. Comme sa réponse, je suis en montrant les Fenêtres solution ici - lancer un bash processus dans Linux plutôt que cmd sous Windows.
Les DÉTAILS d'UTILISATION: La
commands
argument étant passé ici à laprocess.communicate
méthode est un retour à la ligne délimitée chaîne. Si, par exemple vous venez de lire un lot contenu du fichier dans une chaîne, vous pouvez exécuter de cette façon parce qu'il aurait déjà les retours à la ligne. Important: votre chaîne doit se terminer par un saut de ligne"\n"
. Si il ne fait pas, que la finale de la commande n'a pas été exécutée. Tout comme si vous avez tapé dans votre invite de commande mais n'a pas frappé leenter
à la fin. Vous verrez toutefois un mystérieuxMore?
ligne à la fin de la sortie standard (stdout) est retourné. (c'est la cause, si vous rencontrez ce).process.communicate
s'exécute de façon synchrone par définition, et renvoie le stdout et stderr messages (si vous les a dirigés verssubprocess.PIPE
dans votre Popen constructeur).Lorsque vous créez un
cmd.exe
processus de cette façon, et de passer une chaîne de caractères, le résultat sera exactement comme si vous étiez à ouvrir une fenêtre d'invite de commandes et les commandes écrites. Et je veux dire que littéralement. Si vous testez, vous verrez que la sortie standard (stdout) qui est retourné contient vos commandes. (Il n'a PAS d'importance si vous incluez un@echo off
comme si l'exécution d'un fichier de commandes).Conseils pour ceux qui se soucient de "nettoyer" stdout résultats:
@echo off
ne sera pas supprimer vos commandes d'apparaître dans cette chaîne de retour, mais il n'supprimer les retours à la ligne, qui trouvent leur voie dans autrement. (universal_newlines=True bandes d'un autre ensemble de celles-ci)Y compris un
@
symbole du préfixe de vos commandes leur permet de toujours exécuter. Dans un "normal" traitement par lots qui de la, ligne par ligne, de façon à "cacher" vos commandes. Dans ce contexte, il y a fort à un simple marqueur par lequel vous pouvez trouver la sortie standard les lignes que vous souhaitez supprimer. (si l'on a été si incliné)L'cmd.exe "en-tête" apparaîtra dans votre sortie (qui dit que la version de Windows etc.). Depuis, vous voudrez probablement commencer votre jeu de commandes avec
@echo off
, découper l'extra retours à la ligne, qui est aussi un excellent moyen de trouver l'endroit où les lignes d'en-tête s'est arrêté et vos commandes/résultats ont commencé.Enfin, pour répondre aux préoccupations au sujet de "grande" sortie de remplissage des tuyaux et de vous causer des problèmes - d'abord je pense que vous avez besoin d'une ÉNORME quantité de données de revenir, pour que ce soit un problème - plus que la plupart des gens se rencontrer dans leurs cas d'utilisation. Deuxièmement, si c'est vraiment une préoccupation, il suffit d'ouvrir un fichier pour l'écriture et le passer descripteur de fichier (la référence à l'objet de fichier) sur la sortie standard stdout/err au lieu de
PIPE
. Ensuite, faire ce que vous voulez avec le fichier que vous avez créé.Veuillez préciser ce que vous voulez dire ou demander. Si vous avez rencontré cette exception, et souhaitez aider, s'il vous plaît dire quel système d'exploitation que vous utilisez, la version de Python, et, idéalement, de partager votre code exact.
OriginalL'auteur BuvinJ
Celui-ci fonctionne en python 2.7 et devrait fonctionner également sous windows. Probablement quelques petits raffinement est nécessaire pour python >3.
Les produits de sortie est (à l'aide de la date et de sommeil, il est facile de voir que les commandes sont exécutées en ligne):
Comme vous le voyez, les commandes sont exécutées dans une rangée.
C'est ce que je obtenir de la fusion avec @Marichyasana réponse:
Poser est celle-ci ne répondent pas à vos besoins! 😉
Traceback (most recent call last): File "seq_test.py", line 12, in <module> stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()) File "c:\python27\lib\subprocess.py", line 710, in __init__ errread, errwrite) File "c:\python27\lib\subprocess.py", line 958, in _execute_child startupinfo) WindowsError: [Error 2] The system cannot find the file specified
- aucune idée pourquoi? (J'ai remplacé les commandes avec l'écho des commandes conformément à ma question initiale, de sorte que ces commandes peuvent s'exécuter dans Windows)Avez-vous essayé de vos commandes avec un simple Popen/communiquer sur windows? Il se pourrait que les cmd doit être une chaîne de caractères (la lecture de la dernière partie de la sous-processus de la documentation)
Cela n'a pas l'air, il exécute les commandes dans le même processus, qui est une composante fondamentale de cette question.
La question est très claire sur ce point. C'est ce que la question est tout au sujet de base c'est. Les deux exemples de code à exécuter des commandes en séparer les sous-processus, pas la même. Regardez Serge Ballesta réponse, où il a conduites dans plusieurs commandes à la même session shell. Les résultats de ce serait radicalement différent, et répond à la question. Par exemple, si vous avez une commande qui modifie le répertoire, ou affecte une valeur à une variable, avant d'exécuter une autre commande de l'existence d'un second processus est à jeter l'exécution de l'état de la commande!
Oui, vous avez raison....
OriginalL'auteur Riccardo Petraglia
Ici est une fonction (à exécuter) que j'utilise. Je dirais que vous pouvez utiliser pour votre problème. Et il est flexible.
de sortie:
cœur
mon
appartient
pour
papa
code de retour 0
Mise à JOUR: Si vous souhaitez exécuter le même processus, qui va sérialiser les choses pour vous:
1) Supprimer la ligne: les poignées.append(poignée)
2) le remplacement de la variable "gérer" à la place de la liste des "poignées" sur "l'Attente" de la ligne
3) le remplacement de WaitForSingleObject en place de WaitForMultipleObjects
OriginalL'auteur Marichyasana