Rocket Hazmat Rocket Hazmat - 2 months ago 13
Python Question

Variable length arguments

I am creating a python program using the

module and I want to allow the program to take either one argument or 2 arguments.

What do I mean? Well, I am creating a program to download/decode MMS messages and I want the user to either be able to provide a phone number and MMS-Transaction-ID to download the data or provide a file from their system of already downloaded MMS data.

What I want is something like this, where you can either enter in 2 arguments, or 1 argument:

./mms.py (phone mmsid | file)


NOTE:
phone
would be a phone number (like
15555555555
),
mmsid
a string (MMS-Transaction-ID) and
file
a file on the user's computer


Is this possible with
argparse
? I was hoping I could use
add_mutually_exclusive_group
, but that didn't seem to do what I want.

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('phone', help='Phone number')
group.add_argument('mmsid', help='MMS-Transaction-ID to download')
group.add_argument('file', help='MMS binary file to read')


This gives the error (removing
required=True
gives the same error):


ValueError: mutually exclusive arguments must be optional


It looks like it wants me to use
--phone
instead of
phone
:

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--phone', help='Phone number')
group.add_argument('--mmsid', help='MMS-Transaction-ID to download')
group.add_argument('--file', help='MMS binary file to read')


When running my program with no arguments, I see:


error: one of the arguments --phone --mmsid --file is required


This is closer to what I want, but can I make
argparse
do
(--phone --msid) or (--file)
?

Answer

This is a little beyond the scope of what argparse can do, as the "type" of the first argument isn't known ahead of time. I would do something like

import argparse

p = argparse.ArgumentParser()
p.add_argument("file_or_phone", help="MMS File or phone number")
p.add_argument ("mmsid", nargs="?", help="MMS-Transaction-ID")

args = p.parse_args()

To determine whether args.file_or_phone is intended as a file name or a phone number, you need to check whether or not args.mmsid is None.