如何在Python sh模块中不屏蔽交互式vim命令?
import sh
sh.vim("lalala")
在我的控制台里没有显示vim编辑器。设置 _bg=False
这个参数没有任何变化(因为这已经是默认值了)
如果我使用 subprocess
模块,就能正常工作:
import subprocess
subprocess.call(["vim", "lalala"])
1 个回答
问题在于,vim
期望它的输入是一个 TTY(终端),但通过 sh
创建的管道并不是 TTY,而是一个管道。
解决办法是不要试图用管道来拦截 vim
的标准输入输出。因为用管道拦截标准输入输出正是 sh
的主要功能,所以与其想办法去对抗,不如干脆不使用它。你可以直接使用标准库中的 subprocess
模块,只有在你特别要求的情况下,它才会拦截标准输入输出:
subprocess.check_call(['vim', 'lalala'])
不过,注意一下 sh
文档中的 TTYs 部分:
一些应用程序的行为会根据它们的标准文件描述符是否连接到 TTY 而有所不同。例如,当标准输出(STDOUT)没有连接到 TTY 时,
git
会禁用一些面向人类的功能,比如彩色输出和分页输出。其他程序可能会在标准输入(STDIN)没有连接到 TTY 时禁用交互输入。还有一些程序,比如 SSH(不带-n
选项),期望它们的输入来自 TTY/终端。默认情况下,
sh
会为标准输出模拟一个 TTY,但标准输入则不会。你可以通过传入额外的特殊关键字参数来改变这个默认行为……
所以,如果你传入 _tty_in=True
,那么 vim
的输入就会是一个模拟的 TTY,而不是管道。
但这仍然不会有什么太大帮助。它会让 vim
运行,但它会使用 sh
为输入和输出创建的假 TTY,这我想并不是你想要的。(如果你想发送控制序列并捕获和处理它返回的控制序列,直接用脚本写 ed
,或者更好的是 sed
,会简单得多……)
那么,为什么你没有收到任何错误信息或其他正常的行为呢?
这其实是因为 vim
的原因。如果你用 emacs
或任何使用 curses
的应用程序,或者其他许多 TTY 应用程序尝试同样的事情,它们会在错误输出(stderr)中写入错误信息,并以 1 退出,这样你就会看到类似这样的信息:
ErrorReturnCode_1:
RAN: '/usr/bin/emacs -nw'
STDOUT:
STDERR:
emacs: standard input is not a tty