How to get argparse to read arguments from a file with an option after positional arguments
<p>I would like to be able to put command-line arguments in a file, and then pass them to a python program, with argparse, using an option rather than a prefix character, for instance:
<code>
$ python myprogram.py 1 2 --foo 1 -A somefile.txt --bar 2
</code>
This is almost the same as <a href="http://stackoverflow.com/questions/27433316/how-to-get-argparse-to-read-arguments-from-a-file-with-an-option-rather-than-pre">this question</a>, except that I need to have some positional arguments at the start; when that solution calls <code>parse_args</code>, it fails if the file does not have the positional arguments in it.</p>

<p>If <code>somefile.txt</code> contains</p>

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

<p>then </p>

<pre><code>$ python myprogram.py 1 2 --foo 1 @somefile.txt --bar 2
</code></pre>

<p>using the <code>prefix char</code> is effectively the same as</p>

<pre><code>$ python myprogram.py 1 2 --foo 1 one two three --bar 2
</code></pre>

<p>In other words, right at the start of parsing, the @ file is read, and its contents are spliced into the <code>argv</code> list.  From there parsing occurs normally.</p>

<p>One thing I suggested in the other SO question was to implement that splicing yourself, prior to parsing.</p>

<p>The answer that you are referring to uses a <code>custom</code> Action; at the point where the usual <code>Action</code> just places the <code>value</code> in the <code>namespace</code>, this action reads and parses the file:</p>

<pre><code>parser.parse_args(f.read().split(), namespace)
</code></pre>

<p>A variant parses into a new <code>namespace</code> and selectively copies values to the main <code>namespace</code>.</p>

<p>Apparently your problem is that your parser has some required arguments, and this <code>parse_args</code> raises an error if the file does not contain those.  That's not surprising.</p>

<p>One solution is to use a different <code>parser</code> for this file, one that is designed to work with just the content of the file.  I would just define it globally.</p>

<pre><code>alt_parser.parse_args(f.read().split(), namespace)
</code></pre>

<p>In other words, you don't have to use the <code>parser</code> that was passed in as a parameter.</p>

<p>A variation on this is to put the filename in the namespace, and handle it after the first parsing:</p>

<pre><code>args = parser.parse_args()
if args.A:
    argv = open(args.A).read().split()
    args1 = alt_parser.parse_args(argv)
</code></pre>

<p>But you might ask, can't we tell what arguments have already been parsed, and take that into account in handling <code>-A</code>?  The <code>parser</code> is not a state-machine; parsing does not alter any of its attributes.  The only variable that reflects parsing so far is the <code>namespace</code>.  All other parsing variables are local to the calling code.</p>

python argparse