Python: Correct use of Click with __main__ and __init__
Asked Answered
H

1

10

I have been playing around with the Click package and I can't get the following snippit of code to work properly.

import numpy as np
import click

@click.command()
@click.option('--get_print', default = True)

class CustomClass():

     def __init__(s, get_print):

        s.data = np.random.normal(0, 1, 10)
        s.get_print = get_print

        if s.get_print:
            print("get_print =", s.get_print)

     def print_mean(s):

        print("Printing mean:")

        mean_ = np.mean(s.data)

        if s.get_print:

            print(mean_)

if __name__ == '__main__':
    CustomClass().print_mean()

It seems that the print_mean function never gets called. If I comment out the @Click decorator, and manually set get_print=True, the print_mean method gets called just fine.

My suspicion is that @Click somehow sets __main__ and so when I do if __name__ == '__main__' it just calls Click again - but perhaps I'm wrong?

In either case, what is the correct way of using Click, when you want the __init__ method to inherit all the options, and if __name__ == '__main__'to actually be able to call functions inside the class, where the __init__ is defined?

Headband answered 27/2, 2018 at 14:37 Comment(4)
you are decorating a class with @click.command(); the only examples i found decorate functions... (but maybe i missed something in the doc...)Rutaceous
@hiroprotagonist is right. You need to decorate a function.Mccants
@hiroprotagonist & @Stephen Rauch, yes, usually you decorate a function with Click, but I am interested in how __init__ can inherit commands from click, without "taking over" the use of __main__. How else would you use Click together with classes?Headband
why do you insist of having click interact directly with your class and not via a function as in all the examples?Rutaceous
R
7

This is just to illustrate what I mean in my comments. Decorate a function with the click functions and have that function instantiate your class and execute whatever member function you need. This is what the click docs suggests:

import numpy as np
import click

class CustomClass:
    def __init__(self, get_print):
        self.data = np.random.normal(0, 1, 10)
        self.get_print = get_print

        if self.get_print:
            print("get_print =", self.get_print)

    def print_mean(self):
        print("Printing mean:")
        mean_ = np.mean(self.data)
        if self.get_print:
            print(mean_)

@click.command()
@click.option('--get_print', default=True)
def cli(get_print):
    cc = CustomClass(get_print)
    cc.print_mean()

if __name__ == '__main__':
    cli()

...and you probably want get_print to be a flag with default False:

@click.command()
@click.option('--get_print', default=False, is_flag=True, required=False)
def cli(get_print):
    cc = CustomClass(get_print)
    cc.print_mean()
Rutaceous answered 28/2, 2018 at 10:12 Comment(1)
Ah. I get your comments now. I thought you referred to decorating the function inside the class with Click, which made no sense to me. I guess the above works. Thanks!Headband

© 2022 - 2024 — McMap. All rights reserved.