Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Determine actually given command line arguments

41 views
Skip to first unread message

Henry Leyh

unread,
May 15, 2013, 2:34:27 AM5/15/13
to
Hello,
I am writing a program that gets its parameters from a combination of
config file (using configparser) and command line arguments (using
argparse). Now I would also like the program to be able to _write_ a
configparser config file that contains only the parameters actually
given on the commandline. Is there a simple way to determine which
command line arguments were actually given on the commandline, i.e. does
argparse.ArgumentParser() know which of its namespace members were
actually hit during parse_args().

I have tried giving the arguments default values and then looking for
those having a non-default value but this is really awkward, especially
if it comes to non-string arguments. Also, parsing sys.argv looks
clumsy because you have to keep track of short and long options with and
without argument etc. i.e. all things that I got argparse for in the
first place.

Thanks && Greetings,
Henry

Colin J. Williams

unread,
May 15, 2013, 8:03:28 AM5/15/13
to
Try sys.argv

Colin W.

Roy Smith

unread,
May 15, 2013, 8:24:54 AM5/15/13
to
In article <kmva9j$1hbk$1...@gwdu112.gwdg.de>,
Henry Leyh <henry...@ipp.mpg.de> wrote:

> Is there a simple way to determine which
> command line arguments were actually given on the commandline, i.e. does
> argparse.ArgumentParser() know which of its namespace members were
> actually hit during parse_args().

I think what you're looking for is sys.argv:

$ cat argv.py
import sys
print sys.argv

$ python argv.py foo bar
['argv.py', 'foo', 'bar']

Jussi Piitulainen

unread,
May 15, 2013, 8:51:37 AM5/15/13
to
You people should read what you quote, or what you don't quote when
you cut the relevant portion.

Q. ... parsing sys.argv looks clumsy because ...
A. Try sys.argv

I mean, huh?

Dave Angel

unread,
May 15, 2013, 8:51:30 AM5/15/13
to pytho...@python.org
Colin & Roy:
The OP mentioned sys.argv in his original query.

--
DaveA

Henry Leyh

unread,
May 15, 2013, 8:52:59 AM5/15/13
to
Thanks, but as I wrote in my first posting I am aware of sys.argv and
was hoping to _avoid_ using it because I'd then have to kind of
re-implement a lot of the stuff already there in argparse, e.g. parsing
sys.argv for short/long options, flag/parameter options etc.

I was thinking of maybe some sort of flag that argparse sets on those
optional arguments created with add_argument() that are really given on
the command line, i.e. those that it stumbles upon them during parse_args().

Regards,
Henry

Oscar Benjamin

unread,
May 15, 2013, 9:00:50 AM5/15/13
to Henry Leyh, Python List
I don't know about that but I imagine that you could compare values
with their defaults to see which have been changed.


Oscar

Henry Leyh

unread,
May 15, 2013, 9:50:53 AM5/15/13
to
Yes, I was trying that and it sort of works with strings if I use
something sufficiently improbable like "__UNSELECTED__" as default. But
it gets difficult with boolean or even number arguments where you just
may not have valid "improbable" defaults. You could now say, so what,
it's the default anyway. But in my program I would like to distinguish
between given and not given arguments rather than between default and
non-default.

Regards,
Henry

Skip Montanaro

unread,
May 15, 2013, 10:08:12 AM5/15/13
to Henry Leyh, pytho...@python.org
> Yes, I was trying that and it sort of works with strings if I use something sufficiently improbable like "__UNSELECTED__" as default. But it gets difficult with boolean or even number arguments where you just may not have valid "improbable" defaults. You could now say, so what, it's the default anyway. But in my program I would like to distinguish between given and not given arguments rather than between default and non-default.

Initialize all your arg variables to None, then after command line
processing, any which remain as None weren't set on the command line.
At that point, set them to the actual defaults. I think that's a
pretty common idiom.

Note: I am an old cranky dude and still use getopt. This idiom is
pretty easy there. YMMV with argparse or optparse.

Skip

Wayne Werner

unread,
May 15, 2013, 10:16:35 AM5/15/13
to Henry Leyh, pytho...@python.org
On Wed, 15 May 2013, Henry Leyh wrote:
> Yes, I was trying that and it sort of works with strings if I use something
> sufficiently improbable like "__UNSELECTED__" as default. But it gets
> difficult with boolean or even number arguments where you just may not have
> valid "improbable" defaults. You could now say, so what, it's the default
> anyway. But in my program I would like to distinguish between given and not
> given arguments rather than between default and non-default.

Have you looked into docopt? It's pretty awesome, and might really help in
this case.

HTH,
-W

Henry Leyh

unread,
May 15, 2013, 10:39:59 AM5/15/13
to
Unfortunately, argparse wants to know the type of the argument and the
boolean arguments (those with action=store_true) can't be initialized
with None.

However, maybe I could convert boolean arguments to something like

parser.add_argument('--foo', type=str, nargs='?', const='True',
default=None)

I'd then have to check for string 'True' rather than for boolean True,
though.

Regards,
Henry

Skip Montanaro

unread,
May 15, 2013, 10:51:43 AM5/15/13
to Henry Leyh, pytho...@python.org
> However, maybe I could ...

... switch to getopt? <wink>

Skip

Roy Smith

unread,
May 15, 2013, 11:29:18 AM5/15/13
to
In article <kn00fb$8kc$1...@gwdu112.gwdg.de>,
Henry Leyh <henry...@ipp.mpg.de> wrote:
>On 15.05.2013 14:24, Roy Smith wrote:
>> In article <kmva9j$1hbk$1...@gwdu112.gwdg.de>,
>> Henry Leyh <henry...@ipp.mpg.de> wrote:
>>
>>> Is there a simple way to determine which
>>> command line arguments were actually given on the commandline, i.e. does
>>> argparse.ArgumentParser() know which of its namespace members were
>>> actually hit during parse_args().
>>
>> I think what you're looking for is sys.argv:
>>
>> $ cat argv.py
>> import sys
>> print sys.argv
>>
>> $ python argv.py foo bar
>> ['argv.py', 'foo', 'bar']
>
>Thanks, but as I wrote in my first posting I am aware of sys.argv and
>was hoping to _avoid_ using it because I'd then have to kind of
>re-implement a lot of the stuff already there in argparse, e.g. parsing
>sys.argv for short/long options, flag/parameter options etc.

Sorry, I missed that.

I'm not clear on exactly what you're trying to do. You say:

> Now I would also like the program to be able to _write_ a
> configparser config file that contains only the parameters actually
> given on the commandline.

I'm guessing what you're trying to do is parse the command line first,
then anything that was set there can get overridden by a value in the
config file? That seems backwards. Usually, the order is:

1) built-in default
2) config file (possibly a system config file, then a per-user one)
3) environment variable
4) command-line argument

It sounds like you're doing it in the reverse order -- allowing the
config file to override the command line.

Henry Leyh

unread,
May 16, 2013, 1:43:42 AM5/16/13
to
No. The program reads a general config file in $HOME, something like
~/.programrc; then parses the command like for '-c FILE' and, if FILE is
present reads it; then parses the command line remains for more
arguments which overwrite everything previously set. (For the record,
this split parsing is done with two argparse parsers. The first parses
for '-c FILE' with parse_known_args(). If there is a FILE, its contents
is used as defaults for a second parser (using set_options()) which then
parses the remains that were returned by the first parser's
parse_known_args().)

But now I would also like to be able to _write_ such a config file FILE
that can be read in a later run. And FILE should contain only those
arguments that were given on the command line.

Say, I tell argparse to look for arguments -s|--sopt STRING, -i|--iopt
INT, -b|--bopt [BOOL], -C CONFFILE. Then 'prog -s bla -i 42 -C cfile'
should produce a confparser compatible cfile which contains

[my_options]
sopt = blah
iopt = 42

and not 'bopt = False' (if False was the program's default for bopt).

Regards,
Henry

Jussi Piitulainen

unread,
May 16, 2013, 2:08:45 AM5/16/13
to
Henry Leyh writes:

> But now I would also like to be able to _write_ such a config file
> FILE that can be read in a later run. And FILE should contain only
> those arguments that were given on the command line.
>
> Say, I tell argparse to look for arguments -s|--sopt STRING,
> -i|--iopt INT, -b|--bopt [BOOL], -C CONFFILE. Then 'prog -s bla -i
> 42 -C cfile' should produce a confparser compatible cfile which
> contains
>
> [my_options]
> sopt = blah
> iopt = 42
>
> and not 'bopt = False' (if False was the program's default for
> bopt).

Could you instead write those options that differ from the defaults?
You could parse an actual command line and an empty command line, and
work out the difference.

So 'prog -i 3' would not cause 'iopt = 3' to be written if 3 is the
default for iopt, but would that be a problem?

Henry Leyh

unread,
May 16, 2013, 3:29:50 AM5/16/13
to
That's what the program does at the moment. However, I'm not quite
happy with it. Generally, the user doesn't know what's the default and
it would be confusing if 'prog -i 3' doesn't make 'iopt = 3' turn up in
the file at the end. There may also be the case when the user (for
whatever reason) _wants_ the default in the file.

I think I will try the opposite instead: the program writes the whole
set of options to the file. This would produce a complete and
consistent configuration which automatically reflects the hierarchy in
which the options were set. And the user can sort it out by hand if he
wants.

Regards,
Henry

0 new messages