Search code examples
pythonargumentspython-click

Command line arguments to main function while using click


I have this code that works fine:

import click

@click.command(context_settings=dict(help_option_names=['-h', '--help']))
@click.option('--team_name', required=True, help='Team name')
@click.option('--input_file', default='url_file.txt', help='Input file name for applications, URLs')
@click.option('--output_file', default='test_results_file.txt', help='Output file name to store test results')
def main(team_name, input_file, output_file):
    # function body

if __name__ == '__main__':
    main()                  # how does this work?

As you see, main is being called with no arguments though it is supposed to receive three. How does this work?


Solution

  • As mentioned in comments, this is taken care by the decorators. The click.command decorator turns the function into an instance of click.Command.

    Each of options decorators build an instance of a click.Option and attach it to the click.Command object to be used later.

    This click.Command object implements a __call__ method which is invoked by your call to main().

    def __call__(self, *args, **kwargs):
        """Alias for :meth:`main`."""
        return self.main(*args, **kwargs)
    

    It is quite simple and simply invokes click.Command.main().

    Near the top of click.Command.main() is:

    if args is None:
        args = get_os_args()
    else:
        args = list(args)
    

    This code gets argv from the command line or uses a provided list of args. Further code in this method does, among other things, the parsing of the command line into a context, and the eventual calling of your main() with the values from the click.Option instances built earlier:

    with self.make_context(prog_name, args, **extra) as ctx:
        rv = self.invoke(ctx)
    

    This is the source of the mysterious 3 arguments.