如何与假装为终端的子进程交互



我正在尝试与NCURSES程序交互。

作为一个例子,我使用GNU屏幕和运行aptitude里面。(你可以用MC来代替)

下面的程序用-x启动一个屏幕会话,连接到我的会话。

我想通过按箭头向下和箭头向上进行导航。

如果我发送'q'表示退出,我会在我的另一个屏幕会话中看到一个弹出框。

我需要做什么来获得特殊的键,如箭头键工作?

它目前似乎忽略了我正在发送的VT102序列。

from twisted.internet import protocol, reactor
class MyPP(protocol.ProcessProtocol):
    def connectionMade(self):
        reactor.callLater(1.0, self.foo)
    def foo(self):
        self.transport.write('33[B')
    def processExited(self, reason):
        print "processExited, status %s" % (reason.value.exitCode,)
    def outReceived(self, data):
        print data
    def errReceived(self, data):
        print "errReceived!", data
pp = MyPP()
command = ['screen', '-x']
reactor.spawnProcess(pp, command[0], command, {'TERM':'xterm'}, usePTY=True)
reactor.run()

:

  1. Ted告诉我在命令历史中使用ESC [A(向上)和ESC [B(向下)与bash一起工作。

  2. 想知道为什么在aptitude它没有我已经改变了TERM=xterm到TERM=ansi修复它。为什么xterm不能工作呢?

我已经改变了TERM=xterm到TERM=ansi修复它。为什么xterm没有呢工作还是让我困惑。

使用Ubuntu 13.04,看起来ansixterm控制代码不太一样。

$ infocmp ansi | grep cud
        cr=^M, cub=E[%p1%dD, cub1=E[D, cud=E[%p1%dB, cud1=E[B,
        kcud1=E[B, kcuf1=E[C, kcuu1=E[A, khome=E[H, kich1=E[L,
$ infocmp xterm | grep cud
        cud=E[%p1%dB, cud1=^J, cuf=E[%p1%dC, cuf1=E[C,
        kcub1=EOD, kcud1=EOB, kcuf1=EOC, kcuu1=EOA,

…所以看起来你需要发送字符串'33OB'来模拟xterm的向下箭头。

下面的代码为我工作…

import subprocess
import os
import time
# Set TERM=xterm in case it isn't already
os.environ['TERM'] = 'xterm'
# Spawn aptitude
p = subprocess.Popen('aptitude', stdin=subprocess.PIPE)
# Wait for a bit to let it load from cache
time.sleep(5)
# Control it using xterm control codes
p.stdin.write('33OB') # arrow down
time.sleep(1)
p.stdin.write('33OB') # arrow down
time.sleep(1)
p.stdin.write('33OA') # arrow up
time.sleep(1)
p.stdin.write('33OA') # arrow up
time.sleep(1)
p.stdin.write('q')      # quit
time.sleep(1)
p.stdin.write('y')      # confirm

…虽然它在完成后把我的终端搞砸了,所以我不得不做…

$ stty sane

…让它重新工作。


刚刚找到了确定正确控制代码的更简单方法。如果您加载vi,进入插入模式,然后按CTRL-V和您想要模拟的键,它将显示从终端发送的文字字符串。

例如…

Down Arrow: ^[OB
Page Up: ^[[5~

…其中^[CTRL-[,即'33'

对于带有-T选项的特定终端类型,使用tput命令是获取特定终端功能代码的好方法。

在Python中,使用curses模块获得正确的代码:

from curses import *
setupterm('xterm')
key_up = tigetstr("kcuul")
key_down = tigetstr("kcudl")

您可以通过启动man terminfo来阅读可用的功能。上面的例子可能需要savetty()setuptermresetty()之前,在您获得感兴趣的关键代码之后。否则,您的终端可能会处于bad状态。在C语言中,在一些退出处理程序中也有这样的设置,以便在错误时重置终端,但Python模块可以在自己的处理中处理。

与硬编码终端代码相比,这种方法具有在系统之间可移植的优点,其中xtermterminfo可能与当前Linux发行版中的

不同。

也许像Pexpect这样的东西在这里可能有用:

https://pypi.python.org/pypi/pexpect

它是Expect的python实现,它基本上监视输入并根据模式执行操作,就好像有人坐在那里与应用程序交互。

最新更新