向 Python 提供 STDIN 或文件路径名选项单击 CLI 脚本
Supply either STDIN or a file pathname option to Python Click CLI script
我是第一次尝试 Click,但遇到了障碍。
我希望我的(两个)子命令采用文件路径名选项或接受来自 STDIN 的文件内容。
允许:为 --compose-file 使用路径
./docker-secret-helper.py secret-hash-ini --compose-file docker-compose-test.yml
允许:使用文件内容作为标准输入
cat docker-compose-test.yml | ./docker-secret-helper.py secret-hash-ini
(是否应该有一个选项来指示标准输入,例如 -i
或其他?)
不允许:--compose-file 和 stdin 均未通过
./docker-secret-helper.py secret-hash-ini
应该return像这样:You must either pass --compose-file or pipe in 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
我是第一次尝试 Click,但遇到了障碍。
我希望我的(两个)子命令采用文件路径名选项或接受来自 STDIN 的文件内容。
允许:为 --compose-file 使用路径
./docker-secret-helper.py secret-hash-ini --compose-file docker-compose-test.yml
允许:使用文件内容作为标准输入
cat docker-compose-test.yml | ./docker-secret-helper.py secret-hash-ini
(是否应该有一个选项来指示标准输入,例如
-i
或其他?)不允许:--compose-file 和 stdin 均未通过
./docker-secret-helper.py secret-hash-ini
应该return像这样:
You must either pass --compose-file or pipe in 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