杀死less(1)子进程后输入失败

时间:2011-12-21 22:08:22

标签: python unix subprocess

我正在编写一个使用Unix less(1)在终端上显示文本的程序。以下是相关部分:

less = subprocess.Popen(['less -F -'], stdin=subprocess.PIPE, 
            stdout=sys.stdout, shell=True)
try:
    less.stdin.write(rfc_text)
    less.stdin.flush()
    less.stdin = sys.stdin
    less.wait()
except IOError:
    less.terminate()
    return errno.EPIPE
except KeyboardInterrupt:
    less.terminate()
    return 0

在等待较少完成时,我会监听KeyboardInterrupt异常。如果我抓到一个,我用SIGTERM信号减少了,并退出我的程序。

现在,当发生这种情况时,我回到了我的shell提示符,但shell不再回应我写的内容,我必须重置(1)才能使它再次运行。

关于如何在不将我的stdin带入坟墓的情况下减少死亡的任何想法?完整来源可在https://github.com/jforberg/rfc/blob/master/rfc.py

上找到

编辑:经过一些实验,我发现默认情况下,less(1)和man(1)都忽略了control-C笔划。所以简单地忽略它可能是一个可行的选择。我不确定我认为这是正确的做法,所以如果有人有建议我仍然非常感兴趣。

3 个答案:

答案 0 :(得分:1)

最简单的方法是让用户正确退出less(按q):

#!/usr/bin/env python
from subprocess import PIPE, Popen

p = Popen(['less'], stdin=PIPE)
try:
    p.communicate(''.join("%d\n" % i for i in range(1000)))
except KeyboardInterrupt:
    print("Press `q` to exit.")
    p.wait()

答案 1 :(得分:1)

基本上有两种选择:

  1. 较少,man和相关程序不会在control-C上终止,它们只会中止他们当前正在进行的任何操作。所以简单地忽略击键似乎是一种选择。这将保留有用的功能,即可以在不终止程序的情况下中止冗长的操作,例如长搜索。程序也可以像类似程序一样运行(在本例中是Unix人)。

  2. Less接受-K选项,使其在control-C上终止,就像大多数非交互式命令一样。

答案 2 :(得分:0)

啊啊啊! J.F.塞巴斯蒂安解决方案很好,但它并不适用于所有情况。在我的应用程序中,我想使用“less”,如“tail -f”,使用“less + F -S logfilename”。用户必须按CTRL + C才能进入正常模式,并且Q要退出。

为了使此过程顺利进行,我提出了以下6行解决方案(基于J.F.Sebastian代码):

logpath = os.path.join(cwd, "filename.log")
less = Popen(["less","+F","-S", logpath])
retcode = None
while retcode is None:
    try: retcode = less.wait()
    except KeyboardInterrupt: pass

我认为这解决了原作。如果您要输入较少的内容,则可能需要调整所使用的Popen方法:wait()communicate(input)