Python Argparse Ignore Unrecognised Arguments

Python argparse ignore unrecognised arguments

Replace

args = parser.parse_args()

with

args, unknown = parser.parse_known_args()

For example,

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo')
args, unknown = parser.parse_known_args(['--foo', 'BAR', 'spam'])
print(args)
# Namespace(foo='BAR')
print(unknown)
# ['spam']

Argparse: Ignore dashes in unknown arguments or collect values (potentially starting with dashes) until the next known command

For posterity:

There are a few ways of working around this limitation of argparse. I wrapped one up and published it on PyPI. You can use it just like argparse. The only difference is that there is an extra option you can supply as nargs parameter in add_argument. When this option is used, the parser collects all unknown arguments (regardless of whether they start with a hyphen or not) until the next known argument. For more info check out the repo on github.

Allow unknown arguments using argparse

import argparse

parser = argparse.ArgumentParser(description='sample')

# Add mandatory arguments
parser.add_argument('arg1', action="store")
parser.add_argument('arg2', action="store")

# Parse the arguments
args = parser.parse_args()
# sample usage of args
print (float(args.arg1) + float(args.arg2))

python mrjob: ignore unrecognized arguments

I found a workaround solution but I hope there will be a better way of doing this.

I have to define the argument again inside the mrjob class so it can recognize it:

from datetime import datetime
import json
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-t", "--time", help = "Output file")
args, unknown = parser.parse_known_args()

class Calculate(MRJob):
def configure_args(self):
super(Calculate, self).configure_args()
self.add_passthru_arg("-t", "--time", help="output folder for time")

start_time = datetime.now()
Calculate.run()
execute_time = (datetime.now() - start_time).total_seconds()

data = {}
data["step1"] = execute_time
with open(args.time+'/time.json', 'w') as outfile:
json.dump(data, outfile)

And run with this command:

python cal.py data/input/input.txt --output data/output --time data/output

python argparse: unrecognized arguments

Do not pass sys.argv as an argument to parse_args. Just use

option = parser.parse_args()

If you do pass sys.argv to parse_args, then the path or name of the script itself is the first item in sys.argv and thus becomes the value of option.filename. The hehe then becomes an unknown argument.

If you omit sys.argv then parse_args parses sys.argv as expected.

Argparse will not recognize arguments

The problem is that parse_args tries to identify possible options lexically before ever considering the semantics of any actual option.

Since an option taking a variable number of arguments pretty much has to be the last option used alway, consider making --eval a flag which is used to tell your program how to interpret the remaining positonal arguments. Then ls and -l can be offset by --, preventing parse_args from thinking -l is an undefined option.

p.add_argument(
"--eval",
action='store_true',
help="Run any commands with newly updated environment, "
)

# zero or more, so that you don't have to provide a dummy argument
# when the lack of --eval makes a command unnecessary.
# Wart: you can still use --eval without specifying any commands.
# I don't believe argparse alone is capable of handling this,
# at least not in a way that is simpler than just validating
# arguments after calling parse_args().
p.add_argument('cmd_and_args', nargs='*')

Then your command line could look like

>>> p.parse_args('--export FOO=bar --eval -- ls -l'.split())

or even

>>> p.parse_args('--eval --export FOO=bar -- ls -l'.split())

Later, you'll use the boolean value of args.eval to decide how to treat the list args.cmd_and_args.

Important: One wrinkle with this is that you are attaching these options to arbitrary pre-existing parsers, which may have their own positional arguments defined, so getting this to play nice with the original parser might be difficult, if not impossible.


The other option is to take a single argument to be parsed internally.

p.add_arguments("--eval")

...

args = p.parse_args()
cmd_and_args = shlex.split(args.eval) # or similar

Then

>>> p.parse_args(['--export', 'FOO=bar', '--eval', 'ls -l'])

(Note that using str.split isn't going to work for a command line like --export FOO=bar --eval "ls -l".)

argparse library: PythonShell.py: error: unrecognized arguments

If you use argparse.ArgumentParser, then it will retrieve the arguments of the Python interpreter that is attached to your notebook, but not the parameters that you passed to your sample notebook.

If you want to retrieve parameters passed to %run or dbutils.notebook.run function, then you need to use the dbutils.widgets.get function that receives one argument - parameter name. For example, if you put this into your sample notebook:

print("arg1=", dbutils.widgets.get("arg1"))
print("arg2=", dbutils.widgets.get("arg2"))

you'll see as result:

arg1= some_text1
arg2= some_text2

Getting the remaining arguments in argparse

Another option is to add a positional argument to your parser. Specify the option without leading dashes, and argparse will look for them when no other option is recognized.
This has the added benefit of improving the help text for the command:

>>> parser.add_argument('otherthings', nargs='*')
>>> parser.parse_args(['foo', 'bar', 'baz'])
Namespace(i='i.log', o='o.log', otherthings=['foo', 'bar', 'baz'])

and

>>> print parser.format_help()
usage: ipython-script.py [-h] [-i I] [-o O] [otherthings [otherthings ...]]

positional arguments:
otherthings

optional arguments:
-h, --help show this help message and exit
-i I
-o O

argparse: Ignore positional arguments if a flag is set?

You can define your own action class:

class init_action(argparse.Action):
def __init__(self, option_strings, dest, **kwargs):
return super().__init__(option_strings, dest, nargs=0, default=argparse.SUPPRESS, **kwargs)

def __call__(self, parser, namespace, values, option_string, **kwargs):
# Do whatever should be done here
parser.exit()

def get_args():
parser = argparse.ArgumentParser(description="Tool for FOO-ing a BAR.")
parser.add_argument(dest="version", help="The version.")
parser.add_argument(dest="input", help="The input file.")
parser.add_argument(dest="output", help="The output file.")

parser.add_argument("-i", "--init", action=init_action, help="Foo Init.")

return parser.parse_args()


Related Topics



Leave a reply



Submit