简体   繁体   中英

Order of the arguments matters in getopt

My application parses the command line arguments:

import sys
import getopt

arguments = sys.argv[1:]
options, remainder = getopt.getopt(arguments, "aa:bb:cc:dd:h", ["aaaa=", "bbbb=", "cccc=", "dddd=", "help"])

print dict(options)

This works great but at the same time odd: if I put the arguments in the different order, they aren't get parsed

python my_app.py --aaaa=value1 --bbbb=value2 --cccc=value3 --dddd=value4 #ok
python my_app.py --dddd=value4 --bbbb=value2 --cccc=value3 --aaaa=value1 # empty

That's disappointing because the order of the arguments shouldn't matter, should it? Is there any way to solve that?

UPDATE:

python my_app.py -aa value1 # odd, empty { "-a" : "" } 
python my_app.py -a value1 # even this empty { "-a" : "" }

As stated in the first comment to your question, your main example regarding failed parsing of arguments in a different order works just fine:

~/tmp/so$ python my_app.py --aaaa=value1 --bbbb=value2 --cccc=value3 --dddd=value4
{'--aaaa': 'value1', '--cccc': 'value3', '--dddd': 'value4', '--bbbb': 'value2'}
~/tmp/so$ python my_app.py --dddd=value4 --bbbb=value2 --cccc=value3 --aaaa=value1
{'--cccc': 'value3', '--bbbb': 'value2', '--aaaa': 'value1', '--dddd': 'value4'}

If that's not the case for you, please update the script to print the remainder as well, and show its output.

However, you have still misused the getopt library and that's the reason the latest examples you provided don't work as expected. You can't specify more than a single character as an option, since the second character would count as a new separate option. getopt provides no way to differentiate between two consecutive characters that count as a single option (with the first one carrying no argument value, as it is not followed by a colon) or a single option that is composed of two characters. From getopt.getopt 's documentation , with my added emphasis:

options is the string of option letters that the script wants to recognize, with options that require an argument followed by a colon.

Therefore, when getopt parses your arguments, each time it encounters a -a argument, it associates it with the first a option it notices, which in your case is not followed by a colon. Thus, it sets this option, discards its argument value, if there was any (if -aa was passed as an argument to the script, the second a counts as the argument value) and moves on to the next argument.

Finally, regarding getopt and argparse . The documentation clearly advocates argparse :

The getopt module is a parser for command line options whose API is designed to be familiar to users of the C getopt() function. Users who are unfamiliar with the C getopt() function or who would like to write less code and get better help and error messages should consider using the argparse module instead.

More about why argparse is better than both getopt and the deprecated optparse can be read in this PEP and in the answers to this question .
The only functionality that I've found to be supported in getopt while it requires a bit of work in argparse is argument order permutation like that of gnu getopt . However, this question explains how this can be achieved via argparse .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM