#!/usr/bin/env python3 import click @click.command() @click.option('--desiredrange', '-r', default=1) def main(desiredrange): print(desiredrange) print('abcd') main() print('!!!!')
Running the above code gives me the following in the terminal:
1
abcd
But I do not get
!!!!
This scenario is true for other variations of code that include ANYTHING after the main() function. The script exits after executing this function. This is also true for any function i.e. if I placed the print(‘!!!!’) inside another function, then called that function after main(), the script exits after main(), ignoring the second function.
If I removed ‘click’, such that the code looks like:
#!/usr/bin/env python3 def main(): print(1) print('abcd') main() print('!!!!')
I will get the following printed to terminal:
1
abcd
!!!!
I can execute other functions after main(), as well as other commands. I run this script from terminal using ./script.py (applied chmod +x script.py). I also get no errors from BOTH scenarios.
Why is this?
Advertisement
Answer
The function named main
that you defined isn’t actually the one called directly by the line main()
. Instead, the two decorators are creating a new value that wraps the function. This callable (I don’t think it’s necessarily a function, but a callable instance of click.core.Command
; I’m not digging into the code heavily to see exactly what happens.) calls raises SystemExit
in some way, so that your script exits before the “new” main
actually returns.
You can confirm this by explicitly catching SystemExit
raised by main
and ignoring it. This allows the rest of your script to execute.
try: main() except SystemExit: pass print('!!!!')
Remember that decorator syntax is just a shortcut for function application. With the syntax, you can rewrite your code as
import click def main(desiredrange): print(desiredrange) print('abcd') x = main main = click.command(click.option('--desiredrange', '-r', default=1)(main)) y = main assert x is not y main() print('!!!!')
Since the assertion passes, this confirms that the value bound to main
is not your original function, but something else.