0

I have a program which takes folder paths and other inputs through the command line with argparse. I want this script to run automatically on a server, but I also want to keep its argparse functionality in case I want to run the script manually. Is there a way to have the script use pre-generated inputs from a file but also retain its flag based input system with argparse? Here is my current implementation:

parser = argparse.ArgumentParser(description='runs batch workflow on root directory')
parser.add_argument("--root", type=str, default='./', help="the path to the root directory 
                    to process")
parser.add_argument("--data", type=str, default='MS', help="The type of data to calculate ")
args = parser.parse_args()

root_dir = args.root
option = args.data

I'm pretty new to this stuff, and reading the argparse documentation and This stack overflow question is not really what I want, if possible I would like to keep the root and data flags, and not just replace them with an input file or stdin.

accAscrub
  • 609
  • 1
  • 6
  • 11
  • If you put the `argparse` in the `if __name__=='__main__'` block at the end of the file, then it will only be used with the file is called as a script. If the file is imported, the parser is not run, and you can set those parameters via the importing script. – hpaulj Apr 17 '20 at 16:24
  • do you mean having another script that imports this one, and have that script work with input files? That could be a solution, but I am wondering if there is a clever way to do that within this script without having to make another script to import it. – accAscrub Apr 17 '20 at 16:36

1 Answers1

1

If using argparse, the default keyword argument is a good, standard way to approach the problem; embed the default behavior of the program in the script source, not an external configuration file. However, if you have multiple configuration files that you want to deploy differently, the approach you mentioned (pre-generated from an input) is desirable.

argparse to dictionary

The argparse namespace can be converted to a dictionary. This is convenient as we can make a function that accepts a dictionary, or keyword arguments, and have it process the program with a convenient function signature. Also, file parsers can just as easily load dictionaries and interact with the same function. The python json module is used as an example. Of course, others can be used.

Example Python

def main(arg1=None, arg2=None, arg3=None):
    print(f"{arg1}, {arg2}, {arg3}")

if __name__ == "__main__":
    import sys
    import json
    import argparse

    # script called with nothing -- load default
    if len(sys.argv) == 1:
        with open("default.json", "r") as dfp:
            conf = json.load(dfp)
        main(**conf)

    else: # parse arguments
        parser = argparse.ArgumentParser()
        parser.add_argument('-a1', dest='arg1', metavar='arg1', type=str)
        parser.add_argument('-a2', dest='arg2', metavar='arg2', type=str)
        parser.add_argument('-a3', dest='arg3', metavar='arg3', type=str)
        args = parser.parse_args()
        conf = vars(args)
        main(**conf)

default.json

{
    "arg1" : "str1",
    "arg2" : "str2",
    "arg3" : "str3"
}

Using Fire

The python Fire module can be used more conveniently as well. It has multiple modes that the file can be interacted with minimal effort. The github repo is available here.

DBat
  • 588
  • 2
  • 11