-1

I'm struggling to get runtime arguments and combine them into a list. I'd like for run-time arguments to be like the following python main.py --all or python main.py --endpoint1 --endpoint2. I only have 2 endpoints to worry about right now, possibly more in the future, so I'd like the solution to consider that possibility.

main.py looks like this at the moment:

import api_vendor import argparse if __name__ == "__main__": parser = argparse.ArgumentParser(description="Pick args") parser.add_argument("--all", help="Get endpoint", action="store_true") parser.add_argument("--endpoint1", help="Get endpoint1", action="store_true") parser.add_argument("--endpoint2", help="Get endpoint2", action="store_true") get_all = os.getenv("GET_ALL") == "YES" or args.all get_endpoint1 = os.getenv("GET_ENDPOINT1") == "YES" or get_all or args.endpoint1 get_endpoint2 = os.getenv("GET_ENDPOINT2") == "YES" or get_all or args.endpoint2 av = api_vendor.API() if get_all = TRUE or endpoint1 = TRUE: av.get_endpoint(endpoint1=TRUE) if get_all = TRUE or endpoint2 = TRUE: av.get_endpoint(endpoint2=TRUE) 

I don't like this since it's kind of messy and starting to look like spaghetti code. Whichever arguments are set, I'd like to loop through and call get_endpoint something like:

for endpoint in endpoints: av.get_endpoint(endpoint) 
4
  • 2
    Seems argparse nargs is an option Commented Aug 28 at 15:19
  • It looks like you have a working code that you don't like and you want a code review. I recommend Code Review SE Commented Aug 28 at 15:37
  • 1
    some people use vars(args) to convert it to dictionary and it allows to use it with f-string like args[f"endpoint{x}"] - so it can be used in for-loop. And the same you can do with os.getenv(f"GET_ENDPOINT{x}") But if you plan more values then better use other parameters in argparse to get many values. You could even use --endpoints "1,2" to get it as list of numbers.. Shortly: read doc for argparse Commented Aug 28 at 15:46
  • you may even add own function which will parse parameter and then you can send something like this - with range of numbers from 3 to 5 - --endpoints "1,3:5,7" Commented Aug 28 at 15:58

1 Answer 1

1

Let's start at the end and work backwards. You'd like to have a list (or other iterable) of things you can pass into get_endpoint(), something like

# endpoints = ["endpoint1", "endpoint2"] for endpoint in endpoints: kwargs = {endpoint: True} av.get_endpoint(**kwargs) 

If you look at the list of argparse actions, one of the choices is append_const, which adds a fixed value to the end of the destination list. You can use that to have argparse construct the endpoints variable for you.

parser.add_argument("--endpoint1", dest="endpoints", action="append_const", const="endpoint1") parser.add_argument("--endpoint2", dest="endpoints", action="append_const", const="endpoint2") parser.add_argument("--all", dest="endpoints", action="store_const", const=["endpoint1","endpoint2"]) args = parser.parse_args() for endpoint in args.endpoints: ... 

You could also programmatically construct the endpoint listing, which might be easier to scale later.

ALL_ENDPOINTS = ["endpoint1", "endpoint2"] for endpoint in ALL_ENDPOINTS: parser.add_argument(f"--{endpoint}", dest="endpoints", action="append_const", const=endpoint) parser.add_argument("--all", dest="endpoints", action="store_const", const=ALL_ENDPOINTS) 

This will make the endpoint(s) appear in the order they're specified on the command line, which may or may not be what you want. We also still haven't handled the environment-variable settings, but you can't usefully combine action and default. If we have the separate list of all of the possible endpoints, we can also iterate through those (in order), checking both the command-line option and the environment variable.

ALL_ENDPOINTS = [...] # as above parser.add_argument("--all", action="store_true", default=(os.getenv("GET_ALL") == "YES")) args = parser.parse_args() endpoints = ALL_ENDPOINTS if args.all else args.endpoints for endpoint in ALL_ENDPOINTS: if endpoint not in endpoints and os.getenv(f"GET_{endpoint.upper()}") != "YES": continue kwargs = {endpoint: True} av.get_endpoint(**kwargs) 

So this last setup keeps "all" as a special case, using an argparse default to default it to true if the environment variable GET_ALL is set correctly. endpoints is then a list of selected endpoints from the command line, maybe all of them. We then loop through the list of known endpoints in code order, and for each process it only if it's in the command-line list or its respective environment variable is set.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.