从Python脚本运行vi

3 投票
3 回答
2176 浏览
提问于 2025-04-18 18:30

我正在尝试从一个Python脚本(版本2.6.4)中打开一个普通的vi编辑器(在Solaris 10上是/usr/bin/vi),但是无论我怎么做都没有成功。我想让这个脚本把一些数据放到一个临时文件里,然后打开这个文件让用户用vi编辑。理想情况下,我希望脚本在调用vi时能够暂停,等用户编辑完再继续执行,不过如果能把脚本的进程变成vi的进程(通过exec或者其他方法)也可以。

我试过以下几种方法,但每次vi都会打印文件的第一页到屏幕上,然后以“输入读取错误”退出:

os.execlp('vi', 'vi', filename)

os.system('vi' + ' ' + filename)

subprocess.call('vi' + ' ' + filename, shell=True)

为了让你更了解,这里是完整的代码:

#!/usr/bin/python

import sys
import os
import subprocess

fname = "." + str(os.getpid()) + ".pvi.tmp"
f = open(fname, 'w')

f.write("## Remember to save this to a new file if you want to keep it!\n")

for line in sys.stdin:
    f.write(line + "\n")

f.close()

# These all give the error "Input read error"
#os.execlp('vi', 'vi', fname)
#os.system('vi' + ' ' + fname)
#subprocess.call('vi' + ' ' + fname, shell=True)

os.unlink(fname)

我基本上是在尝试模拟将进程通过管道传输到vi,但我这个版本不支持这个功能(vi -不起作用)。我想把它们通过管道传输到这个脚本,然后这个脚本再把输出写入一个临时文件,并在vi中打开它。

任何帮助都将非常感谢!

3 个回答

0

你的 vi 程序的标准输入没有连接到终端。这意味着你无法在命令行中直接输入内容。一个解决办法是打开一个新的终端窗口:

os.system('xterm -e vi ' + fname)
0

你的 system 调用在OSX上对我来说是有效的:

os.system('vi' + ' ' + fname)

这很正常。在这种情况下,有一个需要考虑的事情就是 stdin(标准输入)会发生什么。如果你不进行重定向直接运行这个命令,它是可以正常工作的。但是如果你重定向 stdin,比如用 python scripty.py < input.txt 这样的方式来运行,那么VI就会报错。它会给我一个提示:Vim: Warning: Input is not from a terminal

3

问题在于,vi的标准输入是从你的脚本中继承来的,这意味着它是连接到管道而不是终端的。你可以试试这个:

os.system('vi' + ' "' + fname + '" </dev/tty >/dev/tty 2>&1')

如果fname是来自用户输入的话,这样做是有风险的,因为用户输入可能包含一些特殊字符,这样就可能执行一些意想不到的命令。不过在你的代码中,似乎并不是这样;你是通过确定的方式构造这个值的。

另一种方法是使用exec的某个调用来绕过shell,但这样你就得在Python中处理输入输出的重定向,这样会有点麻烦。是否值得这样做要看你的应用程序的风险程度。不过在你这个特定的情况下,这似乎并不是个问题。

撰写回答