如何使 python 命令行程序自动完成任意事物而不是解释器

Posted

技术标签:

【中文标题】如何使 python 命令行程序自动完成任意事物而不是解释器【英文标题】:How to make a python, command-line program autocomplete arbitrary things NOT interpreter 【发布时间】:2010-09-16 07:14:35 【问题描述】:

我知道如何在 python 解释器(在 unix 上)中设置 python 对象的自动完成。

Google 显示了许多关于如何执行此操作的说明。 很遗憾,参考资料太多,很难找到我需要做的事情,这略有不同。

我需要知道如何在用 python 编写的命令行程序中启用、制表符/自动完成任意项。

我的具体用例是一个需要发送电子邮件的命令行 python 程序。我希望能够在用户键入部分电子邮件地址(并且可以选择按 TAB 键)时自动完成电子邮件地址(我有磁盘上的地址)。

我不需要它在 windows 或 mac 上工作,只需要在 linux 上工作。

【问题讨论】:

这个blog 应该可以通过配置 .pythonrc 文件来解决问题。 【参考方案1】:

这很好用。

#!/usr/bin/python3

import readline
readline.parse_and_bind("tab: complete")

def complete(text,state):
    volcab = ['dog','cat','rabbit','bird','slug','snail']
    results = [x for x in volcab if x.startswith(text)] + [None]
    return results[state]

readline.set_completer(complete)

line = input('prompt> ')

【讨论】:

【参考方案2】:

发布的答案工作正常,但我已经开源了一个我在工作中编写的自动完成库。我们已经在生产中使用了一段时间,它快速、稳定且易于使用。它甚至有一个演示模式,因此您可以在输入单词时快速测试您会得到什么。

要安装它,只需运行:pip install fast-autocomplete

这是一个例子:

>>> from fast_autocomplete import AutoComplete
>>> words = 'book': , 'burrito': , 'pizza': , 'pasta':
>>> autocomplete = AutoComplete(words=words)
>>> autocomplete.search(word='b', max_cost=3, size=3)
[['book'], ['burrito']]
>>> autocomplete.search(word='bu', max_cost=3, size=3)
[['burrito']]
>>> autocomplete.search(word='barrito', max_cost=3, size=3)  # mis-spelling
[['burrito']]

结帐:https://github.com/seperman/fast-autocomplete 获取源代码。

下面是对其工作原理的解释:http://zepworks.com/posts/you-autocomplete-me/

它处理拼写错误并可选择按单词的权重排序。 (假设burritobook 更重要,那么你给burrito 一个更高的“计数”,它会在结果中首先出现在book 之前。

Words 是一本字典,每个单词都可以有一个上下文。例如“计数”、如何显示单词、单词周围的一些其他上下文等。在此示例中,单词没有任何上下文。

【讨论】:

它是否适用于 Windows 和 Linux shell? @Samuel 我听说有人在 Windows 上使用它。唯一在 Windows 上不起作用的是交互模式,它仅用于演示目的。【参考方案3】:

您可以尝试使用Python Prompt Toolkit,这是一个用于在 Python 中构建交互式命令行应用程序的库。

该库可以轻松添加交互式自动完成功能,允许用户使用 Tab 键以可视方式循环浏览可用选项。该库是跨平台的(Linux、OS X、FreeBSD、OpenBSD、Windows)。示例:

(图片来源:pcgli)

【讨论】:

【参考方案4】:

使用 Python 的 readline 绑定。例如,

import readline

def completer(text, state):
    options = [i for i in commands if i.startswith(text)]
    if state < len(options):
        return options[state]
    else:
        return None

readline.parse_and_bind("tab: complete")
readline.set_completer(completer)

官方module docs 没有更详细的信息,请参阅readline docs 了解更多信息。

【讨论】:

请注意,如果您使用 cmd 模块编写命令行,那么有更好的方法可以做到这一点。 请注意,readline 在 Windows 上不起作用。 pyreadline 似乎是一个替代品,但它不适用于 linux。 您可以在 python 文件的开头放置一个条件来检查操作系统并导入readlinepyreadline【参考方案5】:

我很惊讶没有人提到 argcomplete,这是文档中的一个示例:

from argcomplete.completers import ChoicesCompleter

parser.add_argument("--protocol", choices=('http', 'https', 'ssh', 'rsync', 'wss'))
parser.add_argument("--proto").completer=ChoicesCompleter(('http', 'https', 'ssh', 'rsync', 'wss'))

【讨论】:

这是一个旧帖子,也许 argcomplete 那时不存在?感谢您提及它,我认为这正是我的项目所需要的! 与argparse 结合也非常好!【参考方案6】:
# ~/.pythonrc
import rlcompleter, readline
readline.parse_and_bind('tab:complete')

# ~/.bashrc
export PYTHONSTARTUP=~/.pythonrc

【讨论】:

对于mac os,将readline.parse_and_bind('tab:complete')替换为readline.parse_and_bind ("bind ^I rl_complete") 这太棒了。为我工作。感谢分享。 @Mani 我被困了很长时间。非常感谢【参考方案7】:

由于您在问题中说“不是解释器”,我想您不想要涉及 python readline 等的答案。 (edit:事后看来,显然不是这样的。呵呵。反正我觉得这个信息很有趣,所以我把它留在这里。)

我想你可能会关注this。

它是关于向任意命令添加 shell 级补全,扩展 bash 自己的制表符补全。

简而言之,您将创建一个包含 shell 函数的文件,该函数将生成可能的补全,将其保存到 /etc/bash_completion.d/ 并使用命令 complete 注册它。这是来自链接页面的 sn-p:

_foo() 

    local cur prev opts
    COMPREPLY=()
    cur="$COMP_WORDS[COMP_CWORD]"
    prev="$COMP_WORDS[COMP_CWORD-1]"
    opts="--help --verbose --version"

    if [[ $cur == -* ]] ; then
        COMPREPLY=( $(compgen -W "$opts" -- $cur) )
        return 0
    fi

complete -F _foo foo

在这种情况下,键入 foo --[TAB] 将为您提供变量 opts 中的值,即 --help--verbose--version。出于您的目的,您基本上需要自定义放入 opts 的值。

请查看链接页面上的示例,这一切都非常简单。

【讨论】:

其实我就是因为这个来这里 谢谢,这正是我想要的!【参考方案8】:

这是由 ehemient here 提供的完整代码版本(谢谢)。

import readline

addrs = ['angela@domain.com', 'michael@domain.com', 'david@test.com']

def completer(text, state):
    options = [x for x in addrs if x.startswith(text)]
    try:
        return options[state]
    except IndexError:
        return None

readline.set_completer(completer)
readline.parse_and_bind("tab: complete")

while 1:
    a = raw_input("> ")
    print "You entered", a

【讨论】:

请注意,readline 在 Windows 上不起作用,至少在 Python 2.7.18 中不起作用。 pyreadline 似乎是一个主要的替代品,除了你必须用 readline.readline() 替换 raw_input(),【参考方案9】:

关注cmd documentation,你会没事的

import cmd

addresses = [
    'here@blubb.com',
    'foo@bar.com',
    'whatever@wherever.org',
]

class MyCmd(cmd.Cmd):
    def do_send(self, line):
        pass

    def complete_send(self, text, line, start_index, end_index):
        if text:
            return [
                address for address in addresses
                if address.startswith(text)
            ]
        else:
            return addresses


if __name__ == '__main__':
    my_cmd = MyCmd()
    my_cmd.cmdloop()

选项卡的输出 -> 选项卡 -> 发送 -> 选项卡 -> 选项卡 -> f -> 选项卡

(Cmd)
help  send
(Cmd) send
foo@bar.com            here@blubb.com         whatever@wherever.org
(Cmd) send foo@bar.com
(Cmd)

【讨论】:

有什么方法可以控制 readline 如何对它的输出进行分列?所以可以说我希望它在每个项目之间用两个空格进行列化。 当我运行此代码时,选项卡会简单地打印到命令行中。事实上,无论我使用 cmd 还是直接 readline,这都是正确的。 我在 cmd 文档中看到很多 readline 引用。这在 Windows shell 中有效吗? @Hack Saw,我在 MacOS 上遇到了这个问题:捆绑的 readline 与 Linux 上的不一样,所以我切换到 Linux(一个 Raspberry Pi),它立即工作。有一个叫做gnureadline 的东西可能值得一看。

以上是关于如何使 python 命令行程序自动完成任意事物而不是解释器的主要内容,如果未能解决你的问题,请参考以下文章

如何使 Python PyQT 程序无法在 Windows 中打开命令行

使用QT自带命令行来打包程序

如何使delphi VCL应用程序从命令行运行

python tkinter 如何使canvas上的图片随着窗体变化而动态变化?

自动逐行执行Python程序

如何使vuetify的自动完成组件相互独立?