When I run this code I get
AttributeError: 'ArgumentParser' object has no attribute 'max_seed'
Here's the code
import argparse
import ConfigParser
CFG_FILE='/my.cfg'
# Get command line arguments
args = argparse.ArgumentParser()
args.add_argument('verb', choices=['new'])
args.add_argument('--max_seed', type=int, default=1000)
args.add_argument('--cmdline')
args.parse_args()
if args.max_seed:
pass
if args.cmdline:
pass
My source file is called "fuzz.py"
You should first initialize the parser and arguments and only then get the actual arguments from parse_args() (see example from the docs):
import argparse
import ConfigParser
CFG_FILE='/my.cfg'
# Get command line arguments
parser = argparse.ArgumentParser()
parser.add_argument('verb', choices=['new'])
parser.add_argument('--max_seed', type=int, default=1000)
parser.add_argument('--cmdline')
args = parser.parse_args()
if args.max_seed:
pass
if args.cmdline:
pass
Hope that helps.
If you use argparse parsed arguments inside another class (somewhere you do self.args = parser.parse_args() ), you might need to explicitly tell your lint parser to ignore Namespace type checking. As told by #frans at Avoid Pylint warning E1101: 'Instance of .. has no .. member' for class with dynamic attributes
:
Just to provide the answer that works for me now - as [The
Compiler][1] suggested you can add a rule for the problematic class in
your projects .pylintrc:
[TYPECHECK]
ignored-classes=Namespace
[1]: https://stackoverflow.com/users/2085149/the-compiler
Related
I'd like to create an app that either loads a config file or inits a config file. The syntax i would like to achieve:
app /some/path/config.json # loads config.json
or
app init # create a config.json with some predefined stuff
The two different positional arguments would have related optional parameters.
I know I can use subparsers to achieve this:
argument = argparse.ArgumentParser()
subparser = argument.add_subparsers()
config_subparser = subparser.add_parser("config")
config_subparser.add_argument(
'config',
help='Path to configuration file.',
nargs='?'
)
init_subparser = subparser.add_parser("init")
init_subparser.add_argument(
'init',
help='initializes workspace'
)
But my problem is that this code has to be called with an additional 'config' string:
app config config.json
Is it possible to create a "nameless" positional param so that the 'config' string can be left out from the call?
Thanks in advance! :)
I have noticed that the default argument value is not set when the custom namespace object is used:
import argparse
class CliArgs(object):
foo: str = 'not touched'
parser = argparse.ArgumentParser()
parser.add_argument('--foo', default='bar')
args = CliArgs()
parser.parse_args(namespace=args)
print(args.foo) # 'not touched'
print(parser.parse_args()) # 'bar'
ideone: https://ideone.com/7P7VxI
I expected bar to be set in both cases.
Is it expected? I cannot see it in the documentation though.
And if it's expected, is there then really no way to implement that other than using some custom action?
UPD: I reported it as a documentation bug https://bugs.python.org/issue38843
Yes it's expected. EDIT: But only for argparse developers.
See argparse.py
def parse_known_args(...):
# add any action defaults that aren't present
for action in self._actions:
if action.dest is not SUPPRESS:
if not hasattr(namespace, action.dest):
if action.default is not SUPPRESS:
setattr(namespace, action.dest, action.default)
# add any parser defaults that aren't present
for dest in self._defaults:
if not hasattr(namespace, dest):
setattr(namespace, dest, self._defaults[dest])
add any action defaults that aren't present
In your example if you set attribute in default object, effect will be the same:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', default='bar')
args = argparse.Namespace()
args.foo = 'not touched'
parser.parse_args(namespace=args)
print(args.foo) # 'not touched'
I'm trying to access to the "resources" folder with the ArgumentParser.
This code and the "resources" folder are in the same folder...
Just to try to run the code, I've put a print function in the predict function. However this error occurs:
predict.py: error: the following arguments are required: resources_path
How can I fix it?
from argparse import ArgumentParser
def parse_args():
parser = ArgumentParser()
parser.add_argument("resources_path", help='/resources')
return parser.parse_args()
def predict(resources_path):
print(resources_path)
pass
if __name__ == '__main__':
args = parse_args()
predict(args.resources_path)
I am guessing from your error message that you are trying to call your program like this:
python predict.py
The argument parser by default gets the arguments from sys.argv, i.e. the command line. You'll have to pass it yourself like this:
python predict.py resources
It's possible that you want the resources argument to default to ./resources if you don't pass anything. (And I further assume you want ./resources, not /resources.) There's a keyword argument for that:
....
parser.add_argument('resources_path', default='./resources')
...
If I import a Python module that is already using argparse, however, I would like to use argparse in my script as well ...how should I go about doing this?
I'm receiving a unrecognized arguments error when using the following code and invoking the script with a -t flag:
Snippet:
#!/usr/bin/env python
....
import conflicting_module
import argparse
...
#################################
# Step 0: Configure settings... #
#################################
parser = argparse.ArgumentParser(description='Process command line options.')
parser.add_argument('--test', '-t')
Error:
unrecognized arguments: -t foobar
You need to guard your imported modules with
if __name__ == '__main__':
...
against it running initialization code such as argument parsing on import. See What does if __name__ == "__main__": do?.
So, in your conflicting_module do
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Process command line options in conflicting_module.py.')
parser.add_argument('--conflicting', '-c')
...
instead of just creating the parser globally.
If the parsing in conflicting_module is a mandatory part of application configuration, consider using
args, rest = parser.parse_known_args()
in your main module and passing rest to conflicting_module, where you'd pass either None or rest to parse_args:
args = parser.parse_args(rest)
That is still a bit bad style and actually the classes and functions in conflicting_module would ideally receive parsed configuration arguments from your main module, which would be responsible for parsing them.
Day three of learning python.
I'm attempting to understand how to pass flags from the command line and call a function with that flag. However, I'm getting the following error:
Traceback (most recent call last):
File "main.py", line 18, in <module>
parser.add_option("-l", action="callback", callback=printLogs)
AttributeError: 'ArgumentParser' object has no attribute 'add_option'
The code is here:
import argparse
def printLogs():
print("logs!")
parser = argparse.ArgumentParser()
parser.add_argument('-e','--entry', type=str, help='New entry',required=False)
parser.add_option("-l", action="callback", callback=printLogs)
args = parser.parse_args()
I can understand that parser.add_option doesn't exist for parser. This much is clear. I can also see that the OptionParser has been deprecated as per this link. So, OptionParser is out.
The question being: How do I parse the -l argument such that the printLogs function is called when its passed?
The way I would implement this is:
import argparse
def printLogs():
print("logs!")
parser = argparse.ArgumentParser()
parser.add_argument('-e','--entry', type=str, help='New entry')
parser.add_argument("-l", action="store_true", help='print logs')
args = parser.parse_args()
if args.l:
printLogs()
The primary purpose of argparse is to parse the input (sys.argv), and give you a set of argument values (args is a simple namespace object). callbacks is a optparse concept that have not been included in argparse.
The FooAction example in the docs, http://docs.python.org/3.4/library/argparse.html#action, does something like this optparse callback. It prints some information when called, and then does the important thing - set a value in the namespace.