Перенаправить команду на ввод другого в Python - PullRequest
7 голосов
/ 17 сентября 2008

Я хотел бы повторить это в python:

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

(hg cat file.txt выводит самую последнюю зафиксированную версию file.txt)

Я знаю, как передать файл в gvimdiff, но он не примет другой файл:

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

Как добраться до части Python ...

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

Когда вызывается подпроцесс, он просто передает <(hg cat file) в gvimdiff в качестве имени файла.

Итак, есть ли способ перенаправить команду, как это делает bash? Для простоты просто скопируйте файл и перенаправьте его на diff:

diff <(cat file.txt) file.txt

Ответы [ 4 ]

9 голосов
/ 17 сентября 2008

Это можно сделать. Начиная с Python 2.5, однако, этот механизм специфичен для Linux и не переносим:

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()

Тем не менее, в конкретном случае diff вы можете просто взять один из файлов из stdin и избавиться от необходимости использовать рассматриваемые функции, подобные bash:

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]
2 голосов
/ 17 сентября 2008

Это на самом деле пример в документах :

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

что значит для вас:

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]

Это исключает использование специфичных для linux битов / proc / self / fd, что делает его, вероятно, работающим на других устройствах, таких как Solaris и BSD (включая MacOS), и, возможно, даже на Windows.

2 голосов
/ 17 сентября 2008

Также есть модуль команд:

import commands

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

Существует также всплывающий набор функций, если вы хотите получить данные из команды во время ее выполнения.

0 голосов
/ 17 сентября 2008

Меня осенило, что вы, вероятно, ищете одну из всплывающих функций.

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

popen3 (cmd [, bufsize [, mode]]) Выполняет cmd как подпроцесс. Возвращает объекты файла (child_stdout, child_stdin, child_stderr).

Намаст, Mark

...