4

Using python's argparse library, I would like to process the first few command-line arguments and use them to generate a list of choices for the other command-line arguments.

How can I process the first few arguments without argparse complaining about extra arguments that it doesn't expect (which I plan to add later)?

For example, I have a script that gets the username and password from the command-line, uses those to access available properties of an API, and then uses that list to restrict the values of a third argument:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('username', help='Your username.')
parser.add_argument('password', help='Your password.')
args = parser.parse_args() # Error here because a third argument exists on the command-line

response = requests.get(
    url='https://api.example.com/properties',
    auth=(args.username, args.password)
)

parser.add_argument(
    'property',
    choices=response.json()['properties'], # Validates the input
    help='The property you want to access.'
)
args = parser.parse_args()

I know I can just add all the arguments at once, and then validate the third argument myself manually, but I'm wondering if there's a way to natively do what I'm asking in the argparse library?

4
  • 1
    Did you check whether stackoverflow.com/questions/20165843/… answers your question? Commented May 16, 2017 at 0:51
  • argparse is as the name sugests a parser. It has functionalities to verify the data to parse, but this verification has is limits. Doing HTTP lookups is definitely outside of this limits. You have to do it in code. Also consider that your approach would not allow to display help without giving the credentials as arguments, but you don't know how until you see the help. Commented May 16, 2017 at 1:12
  • 1
    @Chih-HsuJackLin although it doesn't directly answer my question, within the accepted answer I see the use of the parse_known_args() function (which I wasn't aware of), which I can use to parse chunks of arguments at a time. @KlausD. I see your point about incomplete help documentation. I'll stick to adding all the arguments at once and verifying it myself. Thank you both. Commented May 16, 2017 at 1:35
  • parse_known_args is the first thing that came to mind as I started to read your question. The relevant docs section: docs.python.org/3/library/argparse.html#partial-parsing. The intermixed subclass that I suggested in the linked SO is probably overkill. I haven't gotten much feedback on that since it was proposed. Commented May 16, 2017 at 2:19

1 Answer 1

3
parser = argparse.ArgumentParser()
parser.add_argument('username', help='Your username.')
parser.add_argument('password', help='Your password.')
parser.add_argument(
    'property',
    help='The property you want to access.'
)
args = parser.parse_args() 

response = requests.get(
    url='https://api.example.com/properties',
    auth=(args.username, args.password)
)
allowed_properties = response.json()['properties']
if args.property not in allowed_properties:
    parser.error('property not in allowed properties')

choices is not a complicated test. I'd recommend parsing all inputs, and then testing for this special case. Overall I think gives you better control, and better help and error display.

The parse_known_args approach is good to learn and occasionally use, but I don't think it's that great for this case. You don't get any extra points for embedding all argument testing in the parser.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.