从Python向Linux控制台插入按键输入
最近我遇到了一个比较奇怪的任务,我需要用DTMF(也就是“触摸音”)音调来控制一台非X系统的Linux电脑的终端。这台电脑有一个可以通过ALSA访问的调制解调器,所以我使用sox的“rec”程序来读取输入。这台电脑是完全孤立的,没有以太网或其他网络接口。现在我用的Goertzel算法效果很好,还有eSpeak语音合成引擎,它是唯一的输出来源;这个系统应该可以和任何触摸音电话一起使用。它可以读取输入(输入是八进制数字,每次一个ASCII字节)以及dash
shell反馈的内容——比如提示符、命令的输出等等,都是用ASCII控制字符的记忆法来表示的。
我现在用来和dash
及其启动的程序进行交互的方法是pexpect
模块。不过,我需要它能够在需要的时候读取光标所在行的全部内容,而我记得pexpect
似乎不能做到这一点(如果可以的话,我也没发现)。我能想到的唯一其他解决方案就是用Python来控制或模拟键盘和控制台驱动程序。
这真的是唯一的解决办法吗(如果是的话,用Python实现可能吗?),还是说还有其他方法可以直接访问控制台的内容?
编辑:通过运气,我最近发现了PExpect的SVN版本有一个pexpect.screen。不过,它没有办法真正运行程序。我得继续关注它的发展。
2 个回答
如果你想要操作控制台的内容,可能需要用到 curses
这个库。它有很多详细的说明,你可以在 这里 找到。你可以看看 window.getch()
和 window.getyx()
这两个函数。
简单的解决办法是使用Linux内核的uinput接口。这个接口可以让你像从一个真实的键盘或鼠标一样,向系统发送按键和鼠标事件。这样一来,你的应用程序就可以变成一个键盘或鼠标了。
因为你在用Python,我建议你看看python-uinput这个模块。
如果你对Python中的二进制输入输出比较熟悉,其实也可以不使用任何库来实现这个功能;你只需要查看一下/usr/include/linux/uinput.h
这个头文件,里面有相关的结构(这个接口是非常稳定的),另外也可以看看一些关于uinput的C语言教程这里。
需要注意的是,访问/dev/uinput
或/dev/input/uinput
设备(具体取决于你的Linux发行版)通常需要管理员权限。我个人建议你以一个专门的用户和组来运行Python服务,并修改或添加一个udev规则(查看rules.d
下的所有文件),这样可以让这个组对uinput设备有读写权限,类似于
SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id"
KERNEL=="uinput", MODE="0660", GROUP="the-dedicated-group"
不过,如果你的Python应用程序只是执行其他程序,你可以把它做成一个终端模拟器——比如使用这个。你也可以不使用额外的库,直接用Python的pty模块来实现;主要的工作是模拟一个带有ANSI转义序列的终端,这样应用程序就不会搞混,而现有的终端模拟器都有这样的代码。