向 Python 提供 STDIN 或文件路径名选项单击 CLI 脚本

Supply either STDIN or a file pathname option to Python Click CLI script

我是第一次尝试 Click,但遇到了障碍。

我希望我的(两个)子命令采用文件路径名选项接受来自 STDIN 的文件内容。

当前脚本

我当前的脚本(仅)接受文件路径名(通过 --compose-file):

#!/usr/bin/env python

import click
from DockerSecretHelper import DockerSecretHelper

CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])

@click.group(context_settings=CONTEXT_SETTINGS)
def cli():
    pass

@cli.command(help="retrieves an ini-style file of variables to be used as env vars for docker-compose commmand")
@click.option('--compose-file', help='compose file to work with', required=True)
def secret_hash_ini(**kwargs):
    helper = DockerSecretHelper()
    print(helper.get_secret_hash_ini_format_from_compose_file(**kwargs))
    # will need some kind of if block to call helper.get_secret_hash_ini_format_from_compose_contents(**kwargs) in the
    #  case of stdin

@cli.command(help="retrieves names/values of external secrets; to be used by `docker secret set`")
@click.option('--compose-file', help='compose file to work with', required=True)
def external_secret_info_json(**kwargs):
    helper = DockerSecretHelper()
    print(helper.get_external_secret_info_as_json_from_compost_file(**kwargs))
    # will need some kind of if block to call helper.get_external_secret_info_as_json_from_compose_contents(**kwargs) in
    # the case of stdin

if __name__ == '__main__':
    cli()

如何实现和强制执行 STDIN 文件路径名(但不能同时执行)。

我愿意更改我的命令语法以更好地遵循可能的约定。

此问题与 Creating command line application in python using Click 类似,因此它可能会提供一些构建块(我在组装时遇到问题)。

我会使用点击的 File 选项类型:

import click
import sys


@click.group()
def cli():
    pass


@cli.command()
@click.option('--compose-file', 
              help='compose file to work with',
              type=click.File('r'),
              default=sys.stdin)
def secret_hash_ini(compose_file):
    with compose_file:
        data = compose_file.read()

    print(data)


if __name__ == '__main__':
    cli()

假设我们有一个包含文本的文件 example.txt

This is a test.

然后我们可以指定一个文件 --compose-file:

$ python docker-secret-helper.py secret-hash-ini --compose-file example.txt
This is a test.

或者我们可以阅读 stdin:

$ python docker-secret-helper.py secret-hash-ini < example.txt
This is a test.

我们无法在 "Neither --compose-file nor stdin passed" 的情况下生成错误,因为 stdin 始终可用。如果我们在不提供 --compose-file 且不重定向 stdin 的情况下调用 docker-secret-helper.py,它只会挂起等待输入。

为了让它更通用,你也可以对输出做同样的事情:

#!/usr/bin/env python
"""
Example to read from stdin and write to stdout when no filenames are given.
"""
import sys
from string import Template
import click

@click.command()
@click.option(
    "--file",
    help="Filename of the template, omit to read from STDIN.",
    type=click.File("rt"),
    default=sys.stdin,
)
@click.option(
    "--out",
    help="File to write the Output to, omit to display on screen.",
    type=click.File("at"),
    default=sys.stdout,
)
def generate(file, out):
    """Read the file, and write to out."""
    template = Template(file.read())
    click.echo("#Write something", file=out)
    ...


if __name__ == "__main__":
    generate()

所以你可以做到 ./my_sript.py < some.tpl > output.txt 以及 ./my_script.py --file=some.tpl --out=output.txt