1

Say you are writing a script you want to be able to either directly execute from the command-line or import the functions elsewhere. As a command-line executable, you may want to pass flags as options. If you are importing the script later, it may become tedious to make each option a parameter in every function. Below I have a script that I hope illustrates my point using the verbosity option.

#!/usr/bin/python

def getArgs():
    parser = argparse.ArgumentParser()
    parser.add_argument('input',type=int)
    parser.add_argument('-v','--verbose',action='store_true')
    return parser.parse_args()

def main(input,verbose):
    result = calculation(input,verbose) 
    if verbose:
        print(str(input) + " squared is " + str(result))
    else:
        print(result)

def calculation(input,verbose):
    if verbose:
        print("Doing Calculation")
    result = input * input
    return result 

if __name__ == '__main__': #checks to see if this script is being executed directly, will not run if imported into another script
    import argparse
    args=getArgs()
    if args.verbose:
        print("You have enabled verbosity")
    main(args.input,args.verbose)

Here's some illustrative execution

user@machine ~ $ ./whatever.py 7
49
user@machine ~ $ ./whatever.py -v 7
You have enabled verbosity
Doing Calculation
7 squared is 49
user@machine ~ $ python
Python 3.7.3 (default, Mar 26 2019, 21:43:19) 
[GCC 8.2.1 20181127] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import whatever
>>> whatever.main(7,False)
49
>>> whatever.main(7,True)
Doing Calculation
7 squared is 49

This script works, but I believe there is a cleaner way to handle the command-line options in the case you import the script later, such as forcing a default option. I suppose one option would be to treat the option as a global variable, but I still suspect there is a less verbose (pun intended) way to include these options in later functions.

T. Zack Crawford
  • 7,646
  • 3
  • 11
  • 18
  • Possible duplicate of [Is it generally a good idea to put a console client into module's \_\_name\_\_ == \_\_main\_\_ section?](https://stackoverflow.com/questions/26876003/is-it-generally-a-good-idea-to-put-a-console-client-into-modules-name) – ivan_pozdeev Jun 07 '19 at 00:29

1 Answers1

1

When you have a number of functions that all share common parameters, put the parameters in an object and consider making the functions methods of its type:

class Square:
  def __init__(self,v=False): self.verb=v
  def calculate(self,x):
    if self.verb: print(…)
    return x*x
  def main(self,x):
    if self.verb: print(…)
    y=self.calculate(x)
    print("%s squared is %s"%(x,y) if self.verb else y)

if __name__=="__main__":
  args=getArgs()
  Square(args.verbose).main(args.input)

(The default of False is generally what an API client wants.)

Davis Herring
  • 36,443
  • 4
  • 48
  • 76