why parseargs stores the argument inside a list - python

I have an argparse that is given a string:
def f():
return 'dummy2'
p = argparse.ArgumentParser()
p.add_argument('--a', nargs=1, type=str)
p.add_argument('--b', nargs='?', const=f(), default=f())
p.parse_args('--a dummy'.split())
The parser namespace is Namespace(a=['dummy'], b='dummy2').
How can I make the argument for a be stored as a string and not as a list of strings?

It's simple, just skip the argument for nargs. Try this:
p = argparse.ArgumentParser()
p.add_argument('--a', type=str)
p.add_argument('--b', nargs='?', const=f(), default=f())
I believe this is what you expected:
p.parse_args('--a dummy'.split())
=> Namespace(a='dummy', b='dummy2')
Quoting the docs:
ArgumentParser objects usually associate a single command-line argument with a single action to be taken. The nargs keyword argument associates a different number of command-line arguments with a single action. The supported values are:
N (an integer). N arguments from the command line will be gathered together into a list ... Note that nargs=1 produces a list of one item. This is different from the default, in which the item is produced by itself.

Related

'Namespace' object is not iterable

Attempting to pass an undetermined amount of integers using argparse. When I input: py main.py 3 2
%%writefile main.py
import sorthelper
import argparse
integers = 0
#top-level parser creation
parser = argparse.ArgumentParser("For sorting integers")
nargs = '+' #-> gathers cmd line arguments into a list
args = parser.add_argument('-f', metavar='N', type=int, nargs='+', help='yada yada yada')
args = parser.parse_args()
print(sorthelper.sortNumbers(args))
%%writefile sorthelper.py
def sortNumbers(args):
sorted(args)
Error Namespace Argument is not iterable
I think is is because I am passing an argument that is not of the correct type. After reading through all the documentation I could find I cannot figure out how to make this work. I want the program to sort the numbers I am passing.
parser.parse_args() returns a Namespace object, which is an object whose attributes represent the flags that were parsed. It is not iterable.
It seems like you want to get the command-line arguments given after -f, in which case you would take that particular flag out of the Namespace object:
print(sorthelper.sortNumbers(args.f))
Also, your code as you currently have it will print None, because sortNumbers() doesn't return anything. The built-in sorted() function does not sort in place (though list.sort() does, if you want to use that), so you have to actually do
def sortNumbers(args):
return sorted(args)

Python Argparse: Return only value without parameter name

I want to access and argument from my Python script using argparse:
parser = argparse.ArgumentParser()
# Required positional argument
parser.add_argument('mode', type=str,
help='Operation mode. Either "one" or "two".')
args = parser.parse_args()
print("Argument values:")
print(args.mode)
The variable "args.mode" contains the parameter name plus the value, like this "--mode One". But I want only the value part ("One"). I know I could split up the string but I want to know WHY argparse returns the parameter name. Is there a way to tell it I only want the value?

Parsing arguments in python returns empty line in terminal

I am unable to receive result in terminal while parsing arguments in python. Below script should work in a simple manner, one function multiplies components while other adds them. User is to choose by typing 1 or 2 which option should be applied.
import argparse
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument('first', type=int, nargs=1)
parser.add_argument('second', type=int, nargs=1)
parser.add_argument('decision' , type=int, nargs=1)
return parser.parse_args()
def multiply(first, second):
print(first * second)
def add(first, second):
print(first + second)
args = parse_args()
if args.decision == 1:
multiply(first, second)
elif args.decision == 2:
add(first, second)
Thank you.
Remove the nargs=1 argument from your add_argument(...) calls. The default is a single argument, so it's unnecessary and not doing what you're expecting.
From the docs (emphasis mine):
ArgumentParser objects usually associate a single command-line argument with a single action to be taken. The nargs keyword argument associates a different number of command-line arguments with a single action. The supported values are:
N (an integer). N arguments from the command line will be gathered together into a list. For example:
... <snipped> ...
Note that nargs=1 produces a list of one item. This is different from the default, in which the item is produced by itself.
Since nargs=1 converts your argument into a list, if args.decision == 1: will never be true.
Also, you should be including args. in your function calls (i.e. doing multiply(args.first, args.second), and similar for add).

Why is there a difference when calling argparse.parse_args() or .parse_args(sys.argv)

I have created the following argument parser in my python code.
parser = argparse.ArgumentParser()
parser.add_argument('projectPath')
parser.add_argument('-project')
parser.add_argument('-release')
parser.add_argument('--test', default=False, action='store_true')
args = parser.parse_args()
and I'm executing my program the following way.
myProgram.py /path/to/file -project super --test
it works fine if I use the sysntax above with
args = parser.parse_args()
However if I take and use the sys.argv as input
args = parser.parse_args(sys.argv)
The parser is suddenly picky about the order of the arguments and I get the unrecognized argument error.
usage: fbu.py [-h] [-project PROJECT] [-release RELEASE] [--test] projectPath
fbu.py: error: unrecognized arguments: /path/to/file
As I can see from the error and also using the -h argument. The path argument must be last and the error makes sense in the last example.
But why does it not care about the order in the first example ?
EDIT: I'm using python version 3.4.3
sys.argv contains the script name as the first item, i.e. myProgram.py. That argument takes the spot of projectPath. Now there's one additional positional argument /path/to/file, which can't be matched to any arguments, hence the error.
Calling parse_args without arguments ArgumentParser is clever enough to omit the script name from being parsed. But when explicitly passing an array of arguments, it can't do that and will parse everything.
As you can see from looking at the source code for parse_known_args (which is called by parse_args):
if args is None:
# args default to the system args
args = _sys.argv[1:]
When you don't provide the arguments explicitly, Python removes the first item from .argv (which is the name of the script). If you pass the arguments manually, you must do this yourself:
parser.parse_args(sys.argv[1:])
This isn't explicitly covered in the documentation, but note that this section doesn't include a script name when calling parse_args manually:
Beyond sys.argv
Sometimes it may be useful to have an ArgumentParser parse arguments
other than those of sys.argv. This can be accomplished by passing a
list of strings to parse_args(). This is useful for testing at the
interactive prompt:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument(
... 'integers', metavar='int', type=int, choices=xrange(10),
... nargs='+', help='an integer in the range 0..9')
>>> parser.add_argument(
... '--sum', dest='accumulate', action='store_const', const=sum,
... default=max, help='sum the integers (default: find the max)')
>>> parser.parse_args(['1', '2', '3', '4'])
Namespace(accumulate=<built-in function max>, integers=[1, 2, 3, 4])
>>> parser.parse_args('1 2 3 4 --sum'.split())
Namespace(accumulate=<built-in function sum>, integers=[1, 2, 3, 4])
The advantage of passing the arguments manually is that it makes it easier to test the parsing functionality, as you can pass in a list of appropriate arguments rather than trying to patch sys.argv.

argparse multiple optional arguments with nargs='?'

I am trying to use argparse to process several optional arguments. Each of the arguments will have a single optional argument as well. For example I have a script called runner.py. I want to call runner.py --functionals --capacity --performance and I want it to use the const values I have set. This part is working. I also want to be able to specify arguments such as --functionals test1 --performance test2 and --capacity test3. Instead of const, now I except the arguments to have the given values. for ex. functionals should be test1, performance test2 etc. What results in the latter case is I get: -c: error: argument --performance: not allowed with argument --functionals
Code for the parser looks like:
def get_parser():
parser = argparse.ArgumentParser(add_help=False)
required_arguments = parser.add_argument_group(title = "required arguments")
test_arguments = parser.add_mutually_exclusive_group()
test_arguments.add_argument(
'--capacity',
nargs='?',
)
test_arguments.add_argument(
'--functionals',
nargs='?',
)
test_arguments.add_argument(
'--performance',
nargs='?',
)
return parser
My mistake was that I was using a mutually exclusive group. I should have been using an regular argument group.

Categories

Resources