2015-03-11 1 views
0

J'appelle un script perl sur un fichier txt externe de python, et j'imprime la sortie dans un fichier de sortie. Mais à la place, je veux rediriger la sortie vers le genre d'unix. En ce moment, je ne suis pas en train de piping, mais d'abord écrire la sortie du programme Perl, puis en combinant mon code sous, et this stackoverflow answer.Résultat de tuyau du sous-processus au tri unix

import subprocess 
import sys 
import os 

for file in os.listdir("."): 

    with open(file + ".out", 'w') as outfile: 
     p = subprocess.Popen(["perl", "pydyn.pl", file], stdout=outfile) 
     p.wait() 
+1

Vous utilisez de manière incorrecte python. Si vous appelez beaucoup de processus externes (comme le tri), au lieu d'utiliser des modules python, il est préférable d'utiliser bash, ipython ou un autre shell. – ventsyv

+1

vous pouvez également diriger le résultat 'p = subprocess.Popen (" perl pydyn.pl% s | sort "% fichier, stdout = outfile, shell = True)' mais pour cela vous allez devoir le faire 'shell = True 'ce qui n'est pas une bonne pratique –

+0

related: [Comment utiliser subprocess.Popen pour connecter plusieurs processus par des tuyaux?] (Http://stackoverflow.com/q/295459/4279) – jfs

Répondre

0

Puisque vous posé la question en python, vous pouvez également diriger le résultat

p = subprocess.Popen("perl pydyn.pl %s | sort" % file, stdout=outfile,shell=True) 

mais pour cela, vous allez devoir le faire shell=True ce qui n'est pas une bonne pratique

est ici d'une façon sans en faire shell=True

p = subprocess.Popen(["perl", "pydyn.pl", file], stdout=subprocess.PIPE) 
    output = subprocess.check_output(['sort'], stdin=p.stdout,stdout=outfile) 
    p.wait() 
+0

'check_output' est incorrect ici; vous ne pouvez pas changer 'stdout'. '"% s "% file' se brise si' file' contient de l'espace ou '$', etc, par exemple, il permet d'exécuter des commandes arbitraires. Vous devriez fermer 'p.stdout' pour un nettoyage correct. Voir [ma réponse] (http://stackoverflow.com/a/29021053/4279) – jfs

1

Utilisez simplement bash. Utiliser python ajoute juste un niveau de complexité dont vous n'avez pas besoin.

for file in $(ls); 
do 
    perl pydyn.pl $file | sort 
done 

Au-dessus est un exemple rapide et sale, une meilleure alternative en termes d'analyse syntaxique est la suivante:

ls | while read file; do perl pydyn.pl "$file" | sort; done 
+0

il échoue sur le premier fichier qui a l'espace dans le nom – jfs

+0

Cela peut être dû à un certain nombre de raisons. J'ai ajouté un autre exemple qui va probablement résoudre le problème. – ventsyv

+0

c'est incorrect. Il devrait être 'lire le fichier', pas' lire $ file'. 'bash' saute ces erreurs * silencieusement *. [Le zen de Python] (https://www.python.org/dev/peps/pep-0020/): * "Les erreurs ne devraient jamais passer silencieusement, sauf si elles sont explicitement passées sous silence." * – jfs

2

Pour imiter la conduite du shell:

#!/usr/bin/env python 
import pipes 
import subprocess 

pipeline = "perl pydyn.pl {f} | sort >{f}.out".format(f=pipes.quote(filename)) 
subprocess.check_call(pipeline, shell=True) 

sans invoquer le shell en Python:

#!/usr/bin/env python 
from subprocess import Popen, PIPE 

perl = Popen(['perl', 'pydyn.pl', filename], stdout=PIPE) 
with perl.stdout, open(filename+'.out', 'wb', 0) as outfile: 
    sort = Popen(['sort'], stdin=perl.stdout, stdout=outfile) 
perl.wait() # wait for perl to finish 
rc = sort.wait() # wait for `sort`, get exit status