How to pass several list of arguments to @click.option
If you don't insist on passing something that looks like a list, but simply want to pass multiple variadic arguments, you can use the multiple
option.
From the click documentation
@click.command()@click.option('--message', '-m', multiple=True)def commit(message): click.echo('\n'.join(message))
$ commit -m foo -m barfoobar
You can coerce click into taking multiple list arguments, if the lists are formatted as a string literals of python lists by using a custom option class like:
Custom Class:
import clickimport astclass PythonLiteralOption(click.Option): def type_cast_value(self, ctx, value): try: return ast.literal_eval(value) except: raise click.BadParameter(value)
This class will use Python's Abstract Syntax Tree module to parse the parameter as a python literal.
Custom Class Usage:
To use the custom class, pass the cls
parameter to @click.option()
decorator like:
@click.option('--option1', cls=PythonLiteralOption, default=[])
How does this work?
This works because click is a well designed OO framework. The @click.option()
decorator usually instantiates a click.Option
object but allows this behavior to be over ridden with the cls
parameter. So it is a relatively easy matter to inherit from click.Option
in our own class and over ride the desired methods.
In this case we over ride click.Option.type_cast_value()
and then call ast.literal_eval()
to parse the list.
Test Code:
@click.command(context_settings=dict(help_option_names=['-h', '--help']))@click.option('--option1', cls=PythonLiteralOption, default=[])@click.option('--option2', cls=PythonLiteralOption, default=[])def cli(option1, option2): click.echo("Option 1, type: {} value: {}".format( type(option1), option1)) click.echo("Option 2, type: {} value: {}".format( type(option2), option2))# do stuffif __name__ == '__main__': import shlex cli(shlex.split( '''--option1 '["o11", "o12", "o13"]' --option2 '["o21", "o22", "o23"]' '''))
Test Results:
Option 1, type: <type 'list'> value: ['o11', 'o12', 'o13']Option 2, type: <type 'list'> value: ['o21', 'o22', 'o23']
The following can be an easier hack fix:
#!/usr/bin/env pythonimport clickimport json@click.command(context_settings=dict(help_option_names=['-h', '--help']))@click.option('--option', help='Whatever')def do_stuff(option): try: option = json.loads(option) except ValueError: pass# do stuffif __name__ == '__main__': do_stuff()
This can help you to use 'option' as a list
or a str
.