2

背景: 我有一个 Python 子进程,它连接到一个类似 shell 的应用程序,该应用程序使用 readline 库来处理输入,并且该应用程序有一个用于命令输入的 TAB 完成例程,就像 bash 一样。生成子进程,如下所示:

def get_cli_subprocess_handle():
    return subprocess.Popen(
                            '/bin/myshell',
                            shell=False,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT,
                            )

一切都很好,除了制表符完成。每当我的 Python 程序将制表符传递'\t'给子进程时,我会在 STDIN 中获得 5 个空格,而不是触发 readline 库的制表符完成例程。:(

问题: 我可以向子进程的 STDIN 发送什么来触发子进程的 tab-complete 功能?也许以另一种方式问:如果可能的话,我如何发送 TAB key而不是 TAB character ?

相关但未得到答复和出轨:

触发围绕readline构建的python批处理的选项卡完成

4

3 回答 3

3

类似外壳的应用程序可能会区分连接到标准输入的终端和连接到它的管道。许多 Unix 实用程序这样做是为了优化它们的缓冲(行与块),类似 shell 的实用程序可能会禁用批处理输入(即 PIPE)的命令完成功能以避免意外结果。命令完成实际上是一个交互式功能,需要终端输入。

检查pty模块并尝试使用主/从对作为子进程的管道。

于 2013-01-28T15:52:59.240 回答
2

确实没有向管道发送制表键这样的事情。管道只能接受位字符串,如果制表符不这样做,则可能没有解决方案。

有一个项目可以做类似的事情,叫做pexpect。只看它的interact()代码,我没有看到任何明显的东西使它工作,而你的却没有。鉴于此,最可能的解释是 pexpect 实际上做了一些工作以使自己看起来像一个伪终端。也许您可以为此合并它的代码?

于 2013-01-28T15:46:36.907 回答
1

根据isedev的回答,我修改了我的代码如下:

import os, pty

def get_cli_subprocess_handle():
    masterPTY, slaveTTY = pty.openpty()
    return masterPTY, slaveTTY, subprocess.Popen(
                                                 '/bin/myshell',
                                                 shell=False,
                                                 stdin=slaveTTY,
                                                 stdout=slaveTTY,
                                                 stderr=slaveTTY,
                                                 )

使用这个返回的元组,我能够根据需要执行,select.select([masterPTY],[],[])并且os.read(masterPTY, 1024)我使用与 pty 模块源中的私有方法非常相似的函数写入 master-pty:

def write_all(masterPTY, data):
    """Successively write all of data into a file-descriptor."""
    while data:
        chars_written = os.write(masterPTY, data)
        data = data[chars_written:]
    return data

感谢所有人提供的良好解决方案。希望这个例子对其他人有所帮助。:)

于 2013-01-29T17:45:54.923 回答