自动响应程序输出

背景

命令行程序往往是为交互式 shell 设计的,这通常表现为等待用户输入或‘提示’。设计良好的程序提供了预先应对此类提示的选项,从而实现易于自动化的工作流程——但对于其他程序,交互性是不可避免的。

幸运的是,Invoke 的 Runner 类不仅将你的标准输入转发给正在运行的程序(允许你手动响应提示),还可以配置为自动代表你进行响应。

基本用法

这种自动化的机制是 Runner.run 方法(及其在其他地方的包装器,如 Context.runinvoke.run)的 watchers 关键字参数,它是 StreamWatcher 子类实例的列表,配置为监视模式并相应地响应。其中最简单的是 Responder,它每次看到其配置的模式时都会回复其配置的响应;其他的可以在 watchers 模块 中找到。

备注

run 的所有其他参数一样,你也可以通过 配置文件 全局设置默认的 watchers 集合。

以这个需要手动响应是/否提示的程序为例:

$ excitable-program
When you give the OK, I'm going to do the things. All of them!!
Are you ready? [Y/n] y
OK! I just did all sorts of neat stuff. You're welcome! Bye!

你*可以*调用 run("excitable-program"),手动监视提示并手动按下 Y。但如果你像这样提供一个 Responder:

@task
def always_ready(c):
    responder = Responder(
        pattern=r"Are you ready? \[Y/n\] ",
        response="y\n",
    )
    c.run("excitable-program", watchers=[responder])

然后 Runner 将程序的 stdoutstderr 传递给 responder,它会监视 "Are you ready? [Y/n] " 并自动写入 y (加上 \n 以模拟按下 Enter/Return)到程序的 stdin

备注

Responder 的 pattern 参数被视为 正则表达式,需要更加小心(注意在上面的示例中我们如何转义方括号),但也提供了更强大的功能。