Comment diriger un appel de sous-processus vers un fichier texte?

93
subprocess.call(["/home/myuser/run.sh", "/tmp/ad_xml",  "/tmp/video_xml"])

Maintenant, j'ai un script que je lance. Lorsque je l'exécute et qu'il atteint cette ligne, il commence à imprimer des éléments car run.sh contient des impressions.

Comment puis-je diriger cela vers un fichier texte également? (Et aussi imprimer, si possible)

TIMEX
la source

Réponses:

171

Si vous souhaitez écrire la sortie dans un fichier, vous pouvez utiliser l' argument stdout de subprocess.call.

Il faut None, subprocess.PIPEun objet de fichier ou un descripteur de fichier. Le premier est la valeur par défaut, stdout est hérité du parent (votre script). Le second vous permet de passer d'une commande / processus à un autre. Les troisième et quatrième sont ce que vous voulez, pour avoir la sortie écrite dans un fichier.

Vous devez ouvrir un fichier avec quelque chose comme openet passer l'entier d'objet ou de descripteur de fichier à call:

f = open("blah.txt", "w")
subprocess.call(["/home/myuser/run.sh", "/tmp/ad_xml",  "/tmp/video_xml"], stdout=f)

J'imagine que tout objet de type fichier valide fonctionnerait, comme une prise (gasp :)), mais je n'ai jamais essayé.

Comme marcog le mentionne dans les commentaires, vous pouvez également rediriger stderr, vous pouvez le rediriger vers le même emplacement que stdout avec stderr=subprocess.STDOUT. Toutes les valeurs mentionnées ci-dessus fonctionnent également, vous pouvez rediriger vers différents endroits.

Skurmedel
la source
5
pourquoi subprocess.call (["echo", "1", ">>", "t.txt"]) ne fonctionne pas?
StackOverflowOfficial
7
@Goldname vous avez besoin d'un shell pour faire la redirection, donc: subprocess.call(["echo", "1", ">>", "t.txt"], shell=True)devrait fonctionner.
Wes Mason
@WesMason Merci, mais je pensais que subprocess.call fonctionnait d'une manière qui ressemblait essentiellement à copier et coller dans le shell?
StackOverflowOfficial
2
@Goldname nah, tout dans le sous-processus repose sur la classe Popen sous-jacente, qui ouvre un processus, shell = True forcera le processus à être exécuté dans le shell par défaut du système (par exemple / bin / sh sur les systèmes POSIX, qui est généralement bash ou dash ), c'est plus sûr de cette façon car vous n'êtes pas ouvert à toutes les fonctionnalités supplémentaires fournies par le shell (tout un langage de programmation en lui-même, avec ses propres exploits si vous passez des données fournies par l'utilisateur). Vérifiez également shlex.quotesi vous transmettez des données potentiellement sales à un sous-shell.
Wes Mason
4
Devrions-nous également fermer le fichier une fois que nous avons terminé? cela fermera le fichier une fois que nous aurons terminé: with open("blah.txt","w") as f: subprocess.call(["/home/myuser/run.sh", "/tmp/ad_xml", "/tmp/video_xml"], stdout=f) @Skurmedel
alper
18

Les options pour popenpeuvent être utilisées danscall

args, 
bufsize=0, 
executable=None, 
stdin=None, 
stdout=None, 
stderr=None, 
preexec_fn=None, 
close_fds=False, 
shell=False, 
cwd=None, 
env=None, 
universal_newlines=False, 
startupinfo=None, 
creationflags=0

Alors...

subprocess.call(["/home/myuser/run.sh", "/tmp/ad_xml",  "/tmp/video_xml"], stdout=myoutput)

Ensuite, vous pouvez faire ce que vous voulez avec myoutput(ce qui devrait être un fichier btw).

En outre, vous pouvez faire quelque chose de plus proche d'une sortie canalisée comme celle-ci.

dmesg | grep hda

serait:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

Il y a beaucoup d'informations intéressantes et utiles sur la page de manuel python .

ocodo
la source