将命令重定向到Python中的另一个输入
我想在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])
当调用 subprocess 时,它只是把 <(hg cat file)
当作文件名传给 gvimdiff
。
那么,有没有办法像 bash 那样重定向一个命令呢?为了简单起见,只需把一个文件的内容输出并重定向到 diff:
diff <(cat file.txt) file.txt
4 个回答
2
还有一个叫做命令模块的东西:
import commands
status, output = commands.getstatusoutput("gvimdiff <(hg cat file.txt) file.txt")
如果你想在命令运行的时候实时获取数据,还有一组叫做popen的函数可以使用。
2
这实际上是一个在文档中的例子:
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这些东西了,这样可能在其他类Unix系统上也能运行,比如Solaris和BSD(包括MacOS),甚至可能在Windows上也能用。
10
这是可以实现的。不过,从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这个具体情况,你可以直接从标准输入中获取其中一个文件,这样就不需要使用那种类似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]