如何不退出单击 CLI?

Ara*_*ght 3 python command-line-interface python-3.x

我正在编写一个 python 脚本,它的行为应该像一个典型的 shell 并提供一些自写函数。它已经工作得很好,但它总是在成功执行命令后退出,因此必须再次启动它才能执行第二个任务。我怎样才能做到,所以它不会以退出代码 0 结束,而是返回到 shell 等待新输入?那么我将如何实现退出方法?以下示例总是在输入 print-a 或 print-b 后退出:

import click
import click_repl
from prompt_toolkit.history import FileHistory
import os

@click.group(invoke_without_command=True)
@click.pass_context
def cli(ctx):
     if ctx.invoked_subcommand is None:
         ctx.invoke(repl)

@cli.command()
def print_a():
    print("a")


@cli.command()
def print_b():
    print("b")


@cli.command()
def repl():
    prompt_kwargs = {
        'history': FileHistory(os.path.expanduser('~/.repl_history'))
    }
    click_repl.repl(click.get_current_context(), prompt_kwargs)

def main():
    while True:
        cli(obj={})


if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

(还有一个额外的问题:在 cmd 包中可以自定义>提示标签,这可以通过单击来实现吗?所以它是类似的东西App>?)

Sam*_*yer 8

使用standalone_mode参数,试试这个:

rv = cli(obj={}, standalone_mode=False)
Run Code Online (Sandbox Code Playgroud)

当解析失败时,上面的代码会抛出一个UsageError. 如果--help获得通过,rv将是整数0。在大多数其他情况下,会返回处理命令的函数的返回值,尽管有一堆异常并且一般行为相当复杂,更多解释在这里:https : //click.palletsprojects.com/en/master /commands/#command-return-values

这种方法的优点是您可以使用命令处理程序的返回值。缺点是当解析失败时你会丢失漂亮的帮助信息(也许有办法恢复它?)。


另一种选择是不使用standalone_mode,而是换您的来电clitry/except那里你赶上一个块SystemExit

try:
    cli(obj={})
except SystemExit as e:
    if e.code != 0:
        raise
Run Code Online (Sandbox Code Playgroud)

通过捕获,SystemExit您可以停止由单击启动的程序退出过程。如果命令解析成功,SystemExit(0)则被捕获。再次注意,解析--help也算作“成功”解析,因此也返回SystemExit(0).

这种方法的缺点是您不能使用命令处理程序的返回值,这使得更难知道何时--help被传递。好处是所有到控制台的帮助消息都被恢复了。

我还应该注意到SystemExit继承自BaseException但不是来自Exception. 因此,要实际捕获,SystemExit您可以直接捕获它或 catch BaseException