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 bar
foo
bar
Answer from Jarno on Stack Overflow
๐ŸŒ
ZetCode
zetcode.com โ€บ python โ€บ click
Python click - creating command line interfaces
January 29, 2024 - If the --shout flag is set, the specified argument is outputted in uppercase. $ ./flags2.py --shout sky SKY $ ./flags2.py --no-shout sky sky ยท Values can be pulled from environment variables. ... #!/usr/bin/python import click import os @click.argument('mydir', envvar='MYDIR', type=click.Path(exists=True)) @click.command() def dolist(mydir): click.echo(os.listdir(mydir)) if __name__ == '__main__': dolist()
๐ŸŒ
Click Documentation
click.palletsprojects.com โ€บ en โ€บ stable โ€บ arguments
Arguments โ€” Click Documentation (8.5.x)
This will assume the argument is required, has no default, and is of the type str. ... @click.command() @click.argument('filename') def touch(filename: str): """Print FILENAME.""" click.echo(filename)
Discussions

python - How to pass several list of arguments to @click.option - Stack Overflow
I want to call a python script through the command line with this kind of parameter (list could be any size, eg with 3): python test.py --option1 ["o11", "o12", "o13"] --option2 ["o21", "o22", "o2... More on stackoverflow.com
๐ŸŒ stackoverflow.com
python - Click command default arguments and/or options - Stack Overflow
The simplest solution for single arguments or options seems to be to just create a variable ARG = click.option(...) and then use @ARG as a decorator of the command function. Applying multiple opts/args at once involves creating a decorator factory or a callable class. This is the cleanest solution I found, credits go to @altendky and @SnoopJ from #python ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
Replacing @click.option with @click.argument in Python - Stack Overflow
I have the following script where I utilize @click.option from the click library in Python. I want to know how to replace it with @click.argument without changing the output. import sys import click More on stackoverflow.com
๐ŸŒ stackoverflow.com
Take arguments after command in click python module - Stack Overflow
Click Version: 6.7 Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] ----------- > --removedigits lower Hi Mom True hi mom ----------- > --removedigits upper Hi Mom True HI MOM ----------- > --removedigits upper Hi1 Mom2 True HI MOM ----------- > ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
June 5, 2018
๐ŸŒ
Click Documentation
click.palletsprojects.com โ€บ en โ€บ stable โ€บ parameters
Parameters โ€” Click Documentation (8.5.x)
In the example, the argumentโ€™s name is filename. The name must match the python arg name. To provide a different name for use in help text, see Placeholder / Meta Variable. The optionโ€™s names are -t and --times. More names are available for options and are covered in Options. @click.command() @click.argument('filename') @click.option('-t', '--times', type=int) def multi_echo(filename, times): """Print value filename multiple times.""" for x in range(times): click.echo(filename)
๐ŸŒ
Real Python
realpython.com โ€บ python-click
Click and Python: Build Extensible and Composable CLI Apps โ€“ Real Python
March 18, 2026 - How can you emulate this behavior using Click and Python? The @click.argument decorator takes an argument called nargs that allows you to predefine the number of values that an argument can accept at the command line.
๐ŸŒ
Snyk
snyk.io โ€บ advisor โ€บ click โ€บ functions โ€บ click.argument
How to use the click.argument function in click | Snyk
@click.argument("file", type=click.Path(exists=True)) @click.argument("namespace", default="default") @click.argument("tag") @click.option("--set", "-s", callback=parse_set, multiple=True) @click.option("--edit", "-e", is_flag=True, help="Edit generated manifest before deploying") @click.option("--timeout", default=300, help="Wait timeout (default 300s, 0 to disable)") @click.pass_context def job(ctx, file, namespace, tag, edit, timeout, **kwargs): exit_status = 0 kwargs["set"].append(("IMAGE_TAG", tag)) manifest = format_yaml(file, namespace, edit=edit, extra=kwargs["set"], print=False) # Modify the name to contain imageTag manifest = list(yaml.load_all(manifest)) found_job = False for item in manifest:
Top answer
1 of 6
93

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 bar
foo
bar
2 of 6
41

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 click
import ast

class 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 stuff
if __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']
๐ŸŒ
AssemblyAI
assemblyai.com โ€บ blog โ€บ the-definitive-guide-to-python-click
The Definitive Guide to Python Click
July 28, 2021 - Now letโ€™s go through how to use the click.options decorator. This decorator is used when you want to pass optional parameters to your commands. It can be used to pass an argument, or to be passed as a flag.
Find elsewhere
๐ŸŒ
Digitalk
digitalk.tech โ€บ blog โ€บ python-click-or-how-to-write-professional-cli-applications
Mndwrk Blog - Python click or how to write professional CLI applications
June 17, 2022 - The order in which they are given does not matter, while arguments are given in a sequence after options have been processed. Take the following example: $ python3 myscript.py --option opt1 -s opt2 arg1 arg2 arg3 ยท In this case --option opt1 and -s opt2 are the options and are defined by the previously demonstrated @click.option decorators, while arg1, arg2, and arg3 are arguments that are defined with @click.argument.
๐ŸŒ
Readthedocs
click-docs-cn.readthedocs.io โ€บ zh-cn โ€บ latest โ€บ arguments.html
Arguments โ€” click
@click.command() @click.argument('filename') def touch(filename): print(filename) And what it looks like: $ python touch.py foo.txt foo.txt ยท The second most common version is variadic arguments where a specific (or unlimited) number of arguments is accepted.
๐ŸŒ
Readthedocs
pymbook.readthedocs.io โ€บ en โ€บ latest โ€บ click.html
Building command line applications with Click โ€” Python for you and me 0.5.beta1 documentation
$ myhello --help Usage: myhello [OPTIONS] This is an example script to learn Click. Options: --verbose Will print verbose messages. -n, --name TEXT Who are you? --password TEXT --help Show this message and exit. $ myhello Password: Repeat for confirmation: Hello World We received hello as password. To learn the full usage of password prompts, read this section. You can also add arguments to your tool.
Top answer
1 of 2
1
import sys
import click
import pandas as pd
from sklearn import metrics
@click.command()

# @click.option('--filename')
## @click.argument('result.csv', type=click.Path(exists=True))
@click.argument('filename', type=click.Path(exists=True))
def main(filename):

    df = pd.read_csv(filename)
    y_test = df["actual"].values
    y_pred = df["predicted"].values

    print('R Squared: ' +  str(metrics.r2_score(y_test, y_pred)))
    
if __name__ == '__main__':
    # sys.argv = ['',  '--filename', 'result.csv']
    sys.argv = ['',  'result.csv']
    main()
2 of 2
0

Instead of a named option @click.option('--filename') you can use the argument decorator and specifying:

  1. the parameter-name of your function like here filename and
  2. the type of the parameter, e.g. a file-path that is validated for existence: click.Path(exists=True)

Click Argument for file-paths

You can define File Path Arguments as follows with click:

@click.command()
@click.argument('filename', type=click.Path(exists=True))
def main(filename):
    print(f"{filename=}")
    df = pd.read_csv(filename)

However this means changing your command-line, e.g. by removing the option '--filename' element from the array:

if __name__ == '__main__':
    sys.argv = ['',  'result.csv']
    main()

Attribute Error

The runtime error mentioned in a comment to guolei's answer:

AttributeError: 'tuple' object has no attribute 'tb_frame'

is most likely not related to your presented Python script (incl. click, pandas or scikit-learn). It rather comes from your runtime-environment like IPython or Jupyter Notebook. See AttributeError: 'TypeError' object has no attribute 'tb_frame' bug ยท Issue #12877 ยท ipython/ipython.

๐ŸŒ
Click Documentation
click.palletsprojects.com โ€บ en โ€บ stable โ€บ documentation
Help Pages โ€” Click Documentation (8.5.x)
Positional arguments: NAME The name to print. Options: --count INTEGER number of greetings --help Show this message and exit. For subcommands, a short help snippet is generated. By default, itโ€™s the first sentence of the docstring. If too long, then it will ellipsize what cannot be fit on a single line with .... The short help snippet can also be overridden with short_help: import click @click.group() def cli(): """A simple command line tool.""" @cli.command('init', short_help='init the repo') def init(): """Initializes the repository."""
Top answer
1 of 1
3

The key to making this work is to save the removedigits value into the context with something like:

Code:

@click.pass_context
def cli(ctx, removedigits):
    ctx.obj = dict(removedigits=removedigits)

Then you can retreive it like:

@click.pass_context
def upper(ctx, arguments):
    click.echo(ctx.obj['removedigits'])

Test Code:

import click


@click.group()
@click.option('--removedigits/--removenodigits', default=False,
              help="To remove digits or not")
@click.pass_context
def cli(ctx, removedigits):
    ctx.obj = dict(removedigits=removedigits)


def removedigits(ctx, a_string):
    if ctx.obj['removedigits']:
        a_string = ''.join(c for c in a_string if not c.isdigit())
    return a_string


@cli.command()
@click.argument('arguments', nargs=-1)
@click.pass_context
def upper(ctx, arguments):
    click.echo(ctx.obj['removedigits'])
    click.echo(removedigits(ctx, ' '.join(arguments).upper()))


@cli.command()
@click.argument('arguments', nargs=-1)
@click.pass_context
def lower(ctx, arguments):
    click.echo(ctx.obj['removedigits'])
    click.echo(removedigits(ctx, ' '.join(arguments).lower()))


if __name__ == '__main__':
    commands = (
        '--removedigits lower Hi Mom',
        '--removedigits upper Hi Mom',
        '--removedigits upper Hi1 Mom2',
        '--removenodigits upper Hi Mom',
        '--removenodigits upper Hi1 Mom2',
        'upper Hi Mom',
        'upper Hi1 Mom2',
        '--help',
    )

    import sys, time
    time.sleep(1)
    print('Click Version: {}'.format(click.__version__))
    print('Python Version: {}'.format(sys.version))
    for cmd in commands:
        try:
            time.sleep(0.1)
            print('-----------')
            print('> ' + cmd)
            time.sleep(0.1)
            cli(cmd.split())

        except BaseException as exc:
            if str(exc) != '0' and \
                    not isinstance(exc, (click.ClickException, SystemExit)):
                raise

Results:

Click Version: 6.7
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> --removedigits lower Hi Mom
True
hi mom
-----------
> --removedigits upper Hi Mom
True
HI MOM
-----------
> --removedigits upper Hi1 Mom2
True
HI MOM
-----------
> --removenodigits upper Hi Mom
False
HI MOM
-----------
> --removenodigits upper Hi1 Mom2
False
HI1 MOM2
-----------
> upper Hi Mom
False
HI MOM
-----------
> upper Hi1 Mom2
False
HI1 MOM2
-----------
> --help
Usage: test.py [OPTIONS] COMMAND [ARGS]...

Options:
  --removedigits / --removenodigits
                                  To remove digits or not
  --help                          Show this message and exit.

Commands:
  lower
  upper
Top answer
1 of 2
5

One way that I have managed to achieve this behaviour was by actually using arguments as below. I'll post this as a workaround, while I try to see if it could be done with an option, and I'll update my post accordingly

@click.command(context_settings={"ignore_unknown_options": True})
@click.argument("options", nargs=-1)
def myscript(options):
    option = False
    if options is ():
        option = False
    if '-o' in options or '--option' in options:
        option = True
    if len(options) > 1:
        option = options[1]
    print(option)

Later Edit Using an option, I have managed to achieve this by adding an argument to the command definition.

@click.command()
@click.option('-o', '--option', is_flag=True, default=False, is_eager=True)
@click.argument('value', nargs=-1)
def myscript(option, value):
    if option and value != ():
        option = value[0]
    print(option)

The nargs can be removed if you only expect at most one argument to follow, and can be treated as not required.

@click.command()
@click.option('-o', '--option', is_flag=True, default=False, is_eager=True)
@click.argument('value', required=False)
def myscript(option, value=None):
    if option and value is not None:
        option = value
    print(option)

It might also be possible by putting together a context generator and storing some state, but that seems the least desirable solution, since you would be relying on the context storing your state.

2 of 2
5

FYI, if anybody bumps into this problem in 2024, it seems that click has made something specific for this use case, see: https://click.palletsprojects.com/en/8.1.x/options/#optional-value

Setting is_flag=False, flag_value=value tells Click that the option can still be passed a value, but if only the flag is given the flag_value is used.

@click.command()
@click.option("--name", is_flag=False, flag_value="Flag", default="Default")
def hello(name):
    click.echo(f"Hello, {name}!")

>> hello
Hello, Default!
>> hello --name Value
Hello, Value!
>> hello --name
Hello, Flag!
๐ŸŒ
Readthedocs
pocoo-click.readthedocs.io โ€บ en โ€บ latest โ€บ arguments
Arguments - the Click Documentation
Starting with Click 2.0, it is also possible to open files in atomic mode by passing atomic=True. In atomic mode, all writes go into a separate file in the same folder, and upon completion, the file will be moved over to the original location. This is useful if a file regularly read by other users is modified. Like options, arguments can also grab values from an environment variable.
๐ŸŒ
dbader.org
dbader.org โ€บ blog โ€บ mastering-click-advanced-python-command-line-apps
Mastering Click: Writing Advanced Python Command-Line Apps โ€“ dbader.org
January 2, 2018 - The most obvious ones are the builtin Python types such as str, int, float but Click also provides additional types: Path, File and more. The complete list is available in the section on Parameter Types. Ensuring that an input value is of a specific type is as easy as you can make it. You simply pass the parameter type youโ€™re expecting to the decorator as type argument ...
๐ŸŒ
Click Documentation
click.palletsprojects.com โ€บ en โ€บ stable โ€บ options
Options โ€” Click Documentation (8.5.x)
More formally, Click will try to infer the decorated function argument name as follows: If a positional argument is a valid Python identifier (and thus does not have dashes), it is chosen. If multiple positional arguments are prefixed with --, the first one declared is chosen.