I'm using the Python Click library for my command-line interface. I'd like to have a command that takes multiple key value pairs. I'm flexible on the api. For example
my_cli my_command FOO=1 BAR=2
or maybe
my_cli my_command FOO 1 BAR 2
or even
my_cli my_command {"FOO": 1, "BAR": 2}
Is there an easy way to do this with Click?
Also, in a serialized pair, a special indicator is used to separate the values within the key-value set. Finally, standard and serialized key-values can contain single or multiple values.
A user interface technique for Mac computers, where the Option key is depressed and held down while the mouse is clicked on an item onscreen. Depending on the context — what is clicked, which app is active, etc., — a variety of functions may be initiated.
Click, or “Command Line Interface Creation Kit” is a Python library for building command line interfaces. The three main points of Python Click are arbitrary nesting of commands, automatic help page generation, and supporting lazy loading of subcommands at runtime.
Click supports two types of parameters for scripts: options and arguments. There is generally some confusion among authors of command line scripts of when to use which, so here is a quick overview of the differences. As its name indicates, an option is optional.
The simplest solution is basically the same thing you'd do with a regular Python function where you wanted an API like this.
Take a single parameter that groups the variable-length stream of arguments into a tuple. Then, what you do depends on whether you want separate arguments:
>>> def func(*args):
... d = dict(zip(args[::2], args[1::2]))
... print(d)
>>> func('FOO', 1, 'BAR', 2)
{'FOO': 1, 'BAR': 2}
… or combined key:value
arguments:
>>> def func(*args):
... d = dict(arg.split(':') for arg in args)
... print(d)
This one is a bit hacky to use, because in Python, arguments aren't just space-separated words, but bear with me on that:
>>> func('FOO:1', 'BAR:2')
{'FOO': 1, 'BAR': 2}
The click
equivalent for the first looks like this:
@click.command()
@click.argument('args', nargs=-1)
def my_command(args):
d = dict(zip(args[::2], args[1::2]))
click.echo(d)
(Obviously you can stick that in a click.group
, etc., just like any other command.)
And now:
$ ./clicky.py FOO 1 BAR 2
{'FOO': 1, 'BAR': 2}
And the second looks like this:
@click.command()
@click.argument('args', nargs=-1)
def my_command(args):
d = dict(arg.split(':') for arg in args)
click.echo(d)
And notice that now, using it is not hacky at all, because to your shell, arguments are just words separated by spaces:
$ ./clicky.py FOO:1 BAR:2
{'FOO': 1, 'BAR': 2}
What if you want to handle both KEY=VALUE
and KEY:VALUE
? Then you just have to write something slightly more complicated than arg.split(':')
. And you'll probably want some better error handling too. But that should be enough to get you started.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With