无法在Python中将输出重定向到脚本时启动交互程序
我有一个Python脚本,需要调用定义好的 $EDITOR
或 $VISUAL
。当我单独运行这个Python脚本时,可以顺利启动 $EDITOR
,但一旦我把内容通过管道传给这个Python脚本,$EDITOR
就无法启动了。目前我使用的是nano,每次都会显示
收到 SIGHUP 或 SIGTERM
这似乎和这里提到的 问题
是一样的。sinister:Programming [1313]$ echo "import os;os.system('nano')" > "sample.py"
sinister:Programming [1314]$ python sample.py
# nano is successfully launched here.
sinister:Programming [1315]$ echo "It dies here." | python sample.py
Received SIGHUP or SIGTERM
Buffer written to nano.save.1
补充说明:在程序内部,我并没有把内容通过管道传给编辑器。代码如下:
editorprocess = subprocess.Popen([editor or "vi", temppath])
editorreturncode = os.waitpid(editorprocess.pid, 0)[1]
2 个回答
2
这里处理的是一个具体的例子:find -type f | vidir -
。
foreach my $item (@ARGV) {
if ($item eq "-") {
push @dir, map { chomp; $_ } <STDIN>;
close STDIN;
open(STDIN, "/dev/tty") || die "reopen: $!\n";
}
你也可以在Python中重新实现这个功能:
#!/usr/bin/python
import os
import sys
sys.stdin.close()
o = os.open("/dev/tty", os.O_RDONLY)
os.dup2(o, 0)
os.system('vim')
当然,这个操作会关闭标准输入的文件描述符,所以如果你打算在启动编辑器后再次读取它,最好在关闭之前先复制一下它的文件描述符。
4
当你把某些东西通过管道传递给一个进程时,这个管道是连接到那个进程的标准输入的。这意味着你的终端输入不会连接到编辑器。大多数编辑器会检查它们的标准输入是不是来自终端(可以参考isatty),而管道并不是终端;如果不是终端,它们就会拒绝启动。在 nano
的情况下,这会导致它退出,并显示你提到的消息:
% echo | nano
Received SIGHUP or SIGTERM
如果你想把输入提供给你的 Python 脚本,并且希望能够将其标准输入传递给一个基于终端的编辑器,你需要通过其他方式提供输入,比如通过一个文件。
现在你已经澄清了你的问题,即你不希望 Python 进程的 stdin
连接到编辑器,你可以按照以下方式修改你的代码:
editorprocess = subprocess.Popen([editor or "vi", temppath],
stdin=open('/dev/tty', 'r'))