2008-09-16 8 views
6

Je voudrais reproduire ce en python:Rediriger commande à l'entrée d'un autre en Python

gvimdiff <(hg cat file.txt) file.txt 

(cat hg file.txt sort la version la plus récente de commis file.txt)

Je sais comment le fichier tuyau à gvimdiff, mais il n'acceptera un autre fichier:

$ hg cat file.txt | gvimdiff file.txt - 
Too many edit arguments: "-" 

se rendre à la partie python ...

# hgdiff.py 
import subprocess 
import sys 
file = sys.argv[1] 
subprocess.call(["gvimdiff", "<(hg cat %s)" % file, file]) 

Lorsque le sous-processus est appelé, il passe simplement <(hg cat file) sur gvimdiff comme nom de fichier.

Alors, est-il possible de rediriger une commande comme le fait bash? Par souci de simplicité tout chat un fichier et le rediriger vers diff:

diff <(cat file.txt) file.txt 

Répondre

9

Il peut être fait. A partir de Python 2.5, cependant, ce mécanisme est spécifique à Linux et non portable:

import subprocess 
import sys 

file = sys.argv[1] 
p1 = subprocess.Popen(['hg', 'cat', file], stdout=subprocess.PIPE) 
p2 = subprocess.Popen([ 
    'gvimdiff', 
    '/proc/self/fd/%s' % p1.stdout.fileno(), 
    file]) 
p2.wait() 

Cela dit, dans le cas particulier de diff, vous pouvez simplement prendre l'un des fichiers de stdin et supprimer la nécessité de utiliser la fonctionnalité bash aussi bien en question:

file = sys.argv[1] 
p1 = subprocess.Popen(['hg', 'cat', file], stdout=subprocess.PIPE) 
p2 = subprocess.Popen(['diff', '-', file], stdin=p1.stdout) 
diff_text = p2.communicate()[0] 
+0

Belle solution. A quoi sert bash: > python -c "import sys; print (sys.argv)" <(echo bonjour) function_proj.cc ['-c', '/ dev/fd/63', ' function_proj.cc '] – gatoatigrado

+0

@gatoatigrado - au moins sur mes systèmes, '/ dev/fd' est un lien symbolique vers'/proc/self/fd' –

2

Il y a aussi le module de commandes:

import commands 

status, output = commands.getstatusoutput("gvimdiff <(hg cat file.txt) file.txt") 

Il y a aussi l'ensemble popen de fonctions, si vous voulez grok réellement les données d'une commande en cours d'exécution.

-1

Il m'est tout simplement venu à l'esprit que vous recherchez probablement l'une des fonctions popen.

de: http://docs.python.org/lib/module-popen2.html

popen3 (cmd [, bufsize [mode]]) Exécute cmd comme un sous-processus. Renvoie les objets du fichier (child_stdout, child_stdin, child_stderr).

namaste, Mark

+0

Je n'ai pas critiqué votre réponse, mais gardez à l'esprit que le module de sous-processus est destiné à remplacer les modules popen *. – tzot

2

Ceci est en fait un exemple dans le docs:

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

qui signifie pour vous:

import subprocess 
import sys 

file = sys.argv[1] 
p1 = Popen(["hg", "cat", file], stdout=PIPE) 
p2 = Popen(["gvimdiff", "file.txt"], stdin=p1.stdout, stdout=PIPE) 
output = p2.communicate()[0] 

Cela supprime l'utilisation des bits de Linux spécifique/proc/self/fd, ce qui en fait probablement travailler sur d'autres unix comme Solaris et les systèmes BSD (y compris Mac OS) et peut-être même travailler sur Windows.

+0

Ceci répond à la question que l'affiche aurait dû poser, et non celle qu'il a faite - mais c'est quand même une bonne réponse, alors je le saisis; J'espère que cela ne vous dérange pas. :) (btw, docs de gvimdiff n'indiquent pas qu'il peut lire à partir de stdin, avez-vous essayé cela?) –

Questions connexes