Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect command to input of another in Python

I would like to replicate this in python:

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

(hg cat file.txt outputs the most recently committed version of file.txt)

I know how to pipe the file to gvimdiff, but it won't accept another file:

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

Getting to the python part...

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

When subprocess is called it merely passes <(hg cat file) onto gvimdiff as a filename.

So, is there any way to redirect a command as bash does? For simplicity's sake just cat a file and redirect it to diff:

diff <(cat file.txt) file.txt
like image 969
alif Avatar asked Sep 16 '08 23:09

alif


2 Answers

It can be done. As of Python 2.5, however, this mechanism is Linux-specific and not 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()

That said, in the specific case of diff, you can simply take one of the files from stdin, and remove the need to use the bash-alike functionality in 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]
like image 175
Charles Duffy Avatar answered Sep 19 '22 04:09

Charles Duffy


There is also the commands module:

import commands

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

There is also the popen set of functions, if you want to actually grok the data from a command as it is running.

like image 44
Mark Hattarki Avatar answered Sep 21 '22 04:09

Mark Hattarki