argparse: how to parse a single string argument OR a file listing many arguments?
<p>I have a use case where I'd like the user to be able to provide, as an argument to argparse, EITHER a single string OR a filename where each line has a string.</p>

<p>Assume the user launches <code>./myscript.py -i foobar</code></p>

<p>The logical flow I'm looking for is something like this:</p>

<p>The script determines whether the string foobar is a readable file.
IF it is indeed a readable file, we call some function from the script, passing each line in <code>foobar</code> as an argument to that function.  If foobar is not a readable file, we call the same function but just use the string <code>foobar</code> as the argument and return. </p>

<p>I have no ability to guarantee that a filename argument will have a specific extension (or even an extension at all). </p>

<p>Is there a more pythonic way to do this OTHER than just coding up the logic exactly as I've described above?   I looked through the <a href="https://docs.python.org/2/howto/argparse.html" rel="nofollow">argparse tutorial</a> and didn't see anything, but it also seems reasonable to think that there would be some specific hooks for filenames as arguments, so I figured I'd ask.  </p>

<p>This doesn't look like an <code>argparse</code> problem, since all you want from it is a string.  That string can be a filename or a function argument.  To a <code>parser</code> these will look the same.  Also <code>argparse</code> isn't normally used to run functions.  It is used to parse the commandline.  Your code determines what to do with that information.</p>

<p>So here's a script (untested) that I think does your task:</p>

<pre><code>import argparse
def somefunction(*args):
    print(args)

if __name__=='__main__':
    parser=argparse.ArgumentParser()
    parser.add_argument('-i','--input')
    args = parser.parse_args()

    try:
        with open(args.input) as f:
            lines = f.read()
            somefunction(*lines)
            # or
            # for line in lines:
            #   somefuncion(line.strip())
    except:
        somefunction(arg.input)
</code></pre>

<p><code>argparse</code> just provides the <code>args.input</code> string.  It's the try/except block that determines how it is used.</p>

<p>================</p>

<p>Here's a prefix char approach:</p>

<pre><code>parser=argparse.ArgumentParser(fromfile_prefix_chars='@',
   description="use &lt;prog -i @filename&gt; to load values from file")
parser.add_argument('-i','--inputs')
args=parser.parse_args()
for arg in args.inputs:
     somefunction(arg)
</code></pre>

<p>this is supposed to work with a file like:</p>

<pre><code> one
 two 
 three
</code></pre>

<p><a href="https://docs.python.org/3/library/argparse.html#fromfile-prefix-chars" rel="nofollow">https://docs.python.org/3/library/argparse.html#fromfile-prefix-chars</a></p>

python argparse