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
Python Re.Sub Back Reference Not Back Referencing
How to Tell a Python Script to Use a Particular Version
How to Get Stable Results with Tensorflow, Setting Random Seed
How to Treat Python Argparse.Namespace() as a Dictionary
How to Leave/Exit/Deactivate a Python Virtualenv
When Should I Be Using Classes in Python
Reference Requirements.Txt for the Install_Requires Kwarg in Setuptools Setup.Py File
How to Check Whether a Variable Is a Class or Not
How to Set Headers Using Python's Urllib
If Two Variables Point to the Same Object, Why Doesn't Reassigning One Variable Affect the Other
Python Saving Multiple Figures into One PDF File
Installing Module from Github Through Jupyter Notebook
How to Set Xlim and Ylim for a Subplot in Matplotlib
Matplotlib Connect Scatterplot Points with Line - Python