Variable length arguments
<p>I am creating a python program using the <a href="https://docs.python.org/3/library/argparse.html"><code>argparse</code> module</a> and I want to allow the program to take either one argument or 2 arguments.</p>

<p>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.</p>

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

<pre><code>./mms.py (phone mmsid | file)
</code></pre>

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

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

<pre><code>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')
</code></pre>

<p>This gives the error (removing <code>required=True</code> gives the same error):</p>

<blockquote>
  <p>ValueError: mutually exclusive arguments must be optional</p>
</blockquote>

<p>It looks like it wants me to use <code>--phone</code> instead of <code>phone</code>:</p>

<pre><code>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')
</code></pre>

<p>When running my program with no arguments, I see:</p>

<blockquote>
  <p>error: one of the arguments --phone --mmsid --file is required</p>
</blockquote>

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

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

<pre><code>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()
</code></pre>

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

python python-3.x argparse