exteral
exteral

Reputation: 1061

Pass argument to a deeply nested function in python

I want to run python task.py --debug in the bash script and now I need to set up "debug" argument for my nested function as follows :

main() : 
    call A_1():
        call A_2():
            ... 
                call A_10():
                    if debug : 
                       print("error")

where A_10 is the 10th nested function and I only need debug argument to take effect in A_10 as shown. Now the brute-force way is to add an argument debug from A_1 to A_10. Is there other more elegant way to implement what I need ?

Upvotes: 1

Views: 677

Answers (3)

Thomas
Thomas

Reputation: 348

I see two possible approaches, depending on your preferences:

1. create an object to manage arguments hierachically

Create an object, eg the Class Args at the top level


class Args:
  """store all your arguments here"""
  foo = 42

  class A_10:
    debug = True

# from anywhere in the script at any nested position, call desired function with corresponding args
A_10(debug=Args.A_10.debug)


By doing so you can simply call A_10(debug=Args.A10.debug).

Pro:

  • no need of globals
  • no need to pass down Args to all parent functions
  • simple
  • autocompletion support for class arguments

Con:

  • hard coding of variable args in script

2. use argparse subcommands

You could kill two (CLI args, hierarchically organized arguments) birds with one stone using argparse subcommands, see https://docs.python.org/3/library/argparse.html#sub-commands

Pro:

  • parse CLI arguments
  • use subcommands to split up the functionality

Con:

  • boilerplate code

Upvotes: 0

Rafael
Rafael

Reputation: 7242

Just define the debug as a variable within main. That will be enough and it will be within the scope of your nested functions.

def main():
    debug = True
    def A_1():
        def A_2():
            def A_10():
                if debug:
                    print("error")
            A_10()
        A_2()
    A_1()

if __name__ == "__main__":
    main()

Or also

def main():
    def A_1():
        def A_2():
            def A_10():
                if debug:
                    print("error")
            A_10()
        A_2()
    A_1()

if __name__ == "__main__":
    debug = True
    main()

In the latter, debug is a global variable.

Upvotes: 2

Telmo Trooper
Telmo Trooper

Reputation: 5694

Arguments are available for any part of the script reading sys.argv, it doesn't matter if its nested.

Example:

hello.py

import sys

def test():
    print(sys.argv)
    if "--debug" in sys.argv:
        print("We're in debug mode.")

def main():
    test()

if __name__ == "__main__":
    main()

If I run python3 hello.py --debug it returns:

['hello.py', '--debug']
We're in debug mode.

Upvotes: 4

Related Questions