Set and require default Python script OptionParser - python

The following "parser.add_option" statements work but if the script is run without an option/arg it will not complain. If an option/argument are not specified I would like it to display help (-h / --help) as default.
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
parser.add_option('-d', '--directory',
action='store', dest='directory',
default=None, help='specify directory')
parser.add_option('-f', '--file',
action='store', dest='filename',
default=None, help='specify file')
parser.add_option('-v', '--version',
action="store_true", dest="show_version",
default=False, help='displays the version number')
(options, args) = parser.parse_args()
#if len(args) < 1:
# parser.error("incorrect number of arguments")
Secondly, if I enable the following snip than I get "error: incorrect number of arguments" even when specifying an option/arg.
if len(args) < 1:
parser.error("incorrect number of arguments")
Thanks.
Updated Code with Traceback error below
def main():
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
parser.add_option('-d', '--directory',
action='store', dest='directory',
default=None, help='specify directory')
parser.add_option('-f', '--file',
action='store', dest='filename',
default=None, help='specify file')
parser.add_option('-v', '--version',
action="store_true", dest="show_version",
default=False, help='displays the version number')
if len(sys.argv) == 1:
parser.print_help()
sys.exit()
(options, args) = parser.parse_args()
#if options.show_version:
# prog = os.path.basename(sys.argv[0])
# version_str = "1.0"
# print "version is: %s %s" % (prog, version_str)
# sys.exit(0)
filenames_or_wildcards = []
# remove next line if you do not want allow to run the script without the -f -d
# option, but with arguments
filenames_or_wildcards = args # take all filenames passed in the command line
# if -f was specified add them (in current working directory)
if options.filename is not None:
filenames_or_wildcards.append(options.filename)
Traceback
$ python boto-backup.py Traceback (most recent call last): File "boto-backup.py", line 41, in <module>
filenames_or_wildcards = args # take all filenames passed in the command line NameError: name 'args' is not defined

I would do something like this:
from optparse import OptionParser
import sys
def main():
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
parser.add_option('-d', '--directory',
action='store', dest='directory',
default=None, help='specify directory')
parser.add_option('-f', '--file',
action='store', dest='filename',
default=None, help='specify file')
parser.add_option('-v', '--version',
action="store_true", dest="show_version",
default=False, help='displays the version number')
if len(sys.argv) == 1:
parser.print_help()
sys.exit()
(options, args) = parser.parse_args()
# rest of program...
if __name__ == '__main__':
main()
So we set up the parser and options, and then check if there was any command-line input.
If none, we print the help message and exit. Otherwise we proceed with program execution.
When run with no command-line arguments the output is:
Usage: your_script_name_here.py [options] arg
Options:
-h, --help show this help message and exit
-d DIRECTORY, --directory=DIRECTORY
specify directory
-f FILENAME, --file=FILENAME
specify file
-v, --version displays the version number
Edit (in response to updated code):
Whitespace/indentation is important in Python.
Make sure that the rest of your code is indented such that it belongs to the main() function.
From filenames_or_wildcards = [] on, your code is outside of the scope of the main() function and thus doesn't have a variable named args.

Related

Arguments in top level parser come before subparsers if it has subparsers

I have this MRE:
import argparse
parser = argparse.ArgumentParser(description='Bundle a Python application')
parser.add_argument(
'-o', '--output', metavar='OUTPUT FILE', dest='file_name', type=str,
default=None)
parser.add_argument(
'--extensions', '--ext', action='store_const', metavar='EXTENSIONS',
dest='extensions', const=True, default=False,
help='Whether to allow the importing of C extensions (not needed if C extensions are optional')
if 0:
actions_parser = parser.add_subparsers(
dest='action', metavar='ACTION', help='Action mod should take')
actions_parser.required = True
build_parser = actions_parser.add_parser("build")
build_parser.add_argument(
dest='root', metavar='PROJECT', type=str, help='Project path',
nargs='?', default='.')
get_parser = actions_parser.add_parser("get")
get_parser.add_argument(
dest='module', metavar='MODULE', type=str, help='Module to download')
args = parser.parse_args()
If you run this with python test.py --ext, this works as expected.
However, if you change the 0 to a 1, then python test.py foo --ext fails, even though it should work. Why?
As it turns out, all the arguments attached to the main parser must be before any subaction, e.g. python test.py --ext foo.

deferring exiting on --help when using parse_known_args()

I have a code that needs to build its command line arguments dynamically, based on configuration file. Schematically, what I end up doing is
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--config", type=str, default="",
help="Path to config file.")
args, unknown = parser.parse_known_args()
#here do stuff with args.config to extend parser list of arguments, and then:
parser.parse_args()
The argument management seems to work perfectly well but the trouble I have is that --help will exit at the first call parse_known_args, instead of the second parser.parse_args() which would have shown all the dynamically added arguments.... Is there a way to solve this?
I had the same problem some time ago. It can be solved by using two parsers.
A first pre-parser, with add_help=False to determine the configuration file;
The second full parser with help.
# test.py
import argparse
# First pre-parser to determine the configuration file
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument("-c", "--config", default="", help="Path to config file.")
args = parser.parse_known_args()
# Do something with args.config
# Full and real parser
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--config", default="", help="Path to config file.")
parser.add_argument("-o", "--option", help="Option with default value from config file")
parser.parse_args()
This result in:
$ python3 test.py --help
usage: test.py [-h] [-c CONFIG] [-o OPTION]
optional arguments:
-h, --help show this help message and exit
-c CONFIG, --config CONFIG
Path to config file.
-o OPTION, --option OPTION
Option with default value from config file

Overwrite a default argument with another one using the command line

can anyone help me to overwrite a default argument with another one passing through the command line ?
this is my code:
parser = argparse.ArgumentParser()
parser.add_argument('log', action='store', help='path to the log file')
parser.add_argument('-f', '--filter', default =['filter.json'], help='path to a filter file')
parser.add_argument('-w', '--waiver', type =list, default = [], action='append', help='path to a waiver file')
args = parser.parse_args()
this is the command line to be used:
python3 script.py -f filter_file -w waiver_file log_file
so, I need to overwrite this default =['filter.json'] with filter_file
But don't know what should I do, can you support please ?
thanks
Your script is working:
My output:
PS C:\Users\xf01145\Documents\Python> & "C:/Program Files/Python37/python.exe"
c:/Users/xf01145/Documents/Python/cli.py log.log -f bla.bla blubb.bla test.test hugo.txt
Namespace(filter=['bla.bla', 'blubb.bla', 'test.test', 'hugo.txt'], log='log.log', waiver=[])
0 bla.bla
1 blubb.bla
2 test.test
3 hugo.txt
PS C:\Users\xf01145\Documents\Python>
from this:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('log', action='store', help='path to the log file')
parser.add_argument('-f', '--filter', default =['filter.json'], help='path to a filter file', nargs='+')
parser.add_argument('-w', '--waiver', type =list, default = [], action='append', help='path to a waiver file')
args = parser.parse_args()
print(args)
for i,item in enumerate(args.filter):
print(i, item)

Argument parser does not accept my data file

Running python 2.7.5 in Spyder, trying to set up an argument parser to import input from a file called data.csv in the same folder as my script. Currently, this part of my function looks like so:
from sys import argv
from argparse import ArgumentParser
def ParseArguments():
parser = ArgumentParser(description='Description of program')
parser.add_argument("-f", type=str, dest="data",
default="", help="Input file", required=True)
parser.add_argument("-o", type=str, dest="output_file",
default="", help="Output file")
parser.add_argument("-p", type=float, dest="first_parameter",
default=0.5, help="First Parameter (decimal)")
parser.add_argument("-n", type=int, dest="second_parameter",
default=0, help="Second Parameter (integer)")
args = parser.parse_args()
def my_function(args):
print "Input file is:", args.data
print "Output file is:", args.output_file
print "Parameter 1 is:", args.first_parameter
print "Parameter 2 is:", args.second_parameter
Then I call it in my main function:
def main(argv):
args = ParseArguments()
my_function(args)
args.data
def read(data):
fh = read(args.data, "data")
(...)
Now, when I try to run this I get the error message:
runfile('C:filepath', wdir='C:/filepath')
usage: code.py [-h] -f DATA [-o OUTPUT_FILE] [-p FIRST_PARAMETER]
[-n SECOND_PARAMETER]
code.py: error: argument -f is required
I can't comprehend how this is not defined - there is a file called data in the working directory, and from my understanding of the argument parser it doesn't care about file types when assigning input, so it should be assigning my data.csv as input. What gives?
Another option might be to just not use the argument parser, of course, and reading the file directly by commands, but I'd like to understand what I've done wrong here all the same.

argparse combine with optional parameter

If the user use the optional parameter -o then the user has to use parameter -b as well.
However, the -b parameter you have to use only if the user set the parameter -o.
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-f', nargs='?', required=True)
parser.add_argument('-o', nargs='?', required=False)
parser.add_argument('-b', nargs='?', required=????)
args = parser.parse_args()
How is it possible to solve this problem?
Add a test after args = parser.parse_args():
if args.o and not args.b:
print >> sys.stderr, 'The -b option is required whenever -o is specified'
sys.exit(1)

Categories

Resources