Python: transition from optparse to argparse

After switching from optparse to argparse, I experience strange errors. Argparse analysis only argues if you leave some free space:

myScript.py -oOpt 

or put an equal sign:

 myScript.py -o=Opt 

and this does not work in the usual way:

 myScript.py -o Opt 

Here is my argparse initialization:

 #!/usr/bin/env python # to get description use the -h flag import argparse, os, sys # ====================== # Python2.7 is expected: if sys.version_info[0] != 2 or sys.version_info[1] < 7: sys.exit('This program needs Python2.7+') # ========== # preambule: desc = """Enter dirs in the current dir and makes gro out of state.cpt there.""" # parser = argparse.ArgumentParser() parser = argparse.ArgumentParser(description=desc, version='2.3', formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('-w', '--workWith', help = 'to specify a Gromacs exec suffix', dest = 'wW', action = 'store', default = '-4.5.5-single', ) parser.add_argument('-g', '--gro', help = '.gro postfix: <nameOfTheDir><postfix>.gro', dest = 'myGroPostfix', action = 'store', default = "_membrane", ) parser.add_argument('-H', '--here', help = 'toggles - single (current) dir behaviour (the output will be state.gro)', dest = 'Here', action = 'store_true', ) parser.add_argument('-D', '--dirs', help = 'include these dirs (python\ rgxp in SINGLE quotes), defaults to \'\'', dest = 'inclDirs', action = 'store', default = '', ) args = parser.parse_args() print args.wW 

Edit

Even more:

  gmx_bk-simulate-mems.py -j bk-runs-mpi.bash -p 1 -w="-4.5.5-double_non-parallel_gcc" 2&> ../`date +%Y-%b-%d-%H%M%S`.log & 

gives:

  gmx_bk-simulate-mems.py: error: unrecognized arguments: 2 

it looks like argparse treats 2&> as an option (or 2&> and ../date +%Y-%b-%d-%H%M%S.log as options)!

Edit 2 :

So, we summarize:

  • For argparse - "-4.5.5-double_non-parallel_gcc" is the wrong parameter name - and therefore it must be written as -w="-4.5.5-double_non-parallel_gcc" . For optparse and bash (!) This is great. bash even gives an error when -w="-4.5.5-double_non-parallel_gcc" - he believes that arg ="-4.5.5-double_non-parallel_gcc" (!);

  • There is no such thing as 2&> . 2> should be used and does not give errors;

  • This is a shell that breaks a string into args, not python ;

  • argparse much better than optparse .

+6
source share
1 answer

First, you need to make a slight difference. The argparse module argparse not parse command line arguments like the shell does. The shell is responsible for converting the string you enter into the shell into tokens, which are then passed to sys.argv , python array / sequence of command line arguments. The argparse module just makes sense that appears in sys.argv .

This difference will clarify both of the “mistakes” you have noticed. First, consider -w "-4.5.5-double_non-parallel_gcc" (note the lack of an equal sign). The shell parses these two tokens as -w and -4.5.5-double_non-parallel_gcc , and both of these lines are passed to sys.argv. Without an equal sign, it looks like two parameters: -w (without an argument) and -4 with .5.5-double_non-parallel_gcc as an argument. You need an equal sign so that everything is parsed as a single token.

DEVELOPED SECTION

As for 2&> , for argparse it is impossible to control whether a given token is considered as an argument or not. If something appears in sys.argv, it means that your shell considers it as an argument.

The pilot icon is an error message. Note that the message is not unrecognized arguments: 2&> , but rather unrecognized arguments: 2 . Your shell recognizes "&>" as output redirection and accordingly analyzes the rest of the line (including the log file). The only argument that is passed is "2" because 2&> not a real type of redirect. ( &> already covers both stderr and stdout, so what would add 2 ?)

In a comment, you argued that optparse could "handle" 2 &> ". This is actually not the case. The optparse module did exactly what argparse does, but optparse does not check for positional arguments such as argparse . In fact, optparse makes a real programming error (in this case, using 2&> as a type of shell redirection), gliding over undetected! You should post your original optparse code, but I suspect you have analyzed your arguments as follows:

 opt, args = parser.parse_args() 

Your script does not accept positional arguments, so I think you haven’t done anything else with args . But if you checked args , you will find that 2 was considered a positional argument!

In general, if the script does not accept positional arguments, and you use optparse , a good check is that you are not receiving positional arguments, for example:

 opt, args = parser.parse_args() if args: parser.error("script takes no positional arguments") 

The argparse module does this for you, which makes it miles ahead of optparse (among other reasons).

+12
source

Source: https://habr.com/ru/post/912764/


All Articles