python argparse default arguments versus given arguments - python

Using python 3.8 argparse:
def_value= 'whatever'
argParser.add_argument ("-w", "--whatever", type=str, nargs=1, default=def_value, help="Whatever. Defaults to %s" % def_value)
args= argParser.parse_args()
print (args.whatever)
If I call my program passing a option -w with a value, args.whatever is a list. I mean:
myprog -w just_a_test
[just_a_test]
but, I pass nothing, the default argument is a string.
myprog
whatever
This is annoying, I mean, I have to test the type of args.whatever before using it;
If it is a is a string, just use it as string; if it is a list, I have to use it as args.whatever[0], you see ?
What is the best way to deal with such thing ?
PS: I think it is specific to 3.x, as I recall 2.x returned strings all the time.

did you try to remove the nargs option?

using n_args parameter will wrap the value in a list, therefore, there are two options:
1.
remove nargs argument.
def_value= 'whatever'
argParser.add_argument("-w", "--whatever", type=str, default=def_value, help="Whatever. Defaults to %s" % def_value)
args= argParser.parse_args()
print(args.whatever)
argparse by default allows only one arg, so in this case, no matter passing an argument or not, you will always get a string, and you will get an error when you try to pass more than 1 value.
2.wrap def_value with a list:
def_value= ['whatever']
argParser.add_argument("-w", "--whatever", type=str, nargs=1, default=def_value, help="Whatever. Defaults to %s" % def_value)
args= argParser.parse_args()
print(args.whatever)
now both default and passed in value will be a list with a single string, and it will also raise an error when you pass more than 1 value.
Both solutions above should accomplish the same goal, depending on which you prefer

Related

what if conditional expression might not exist?

is there a better/shorter/more normal way of doing this:
try:
sys.argv[1]
except:
mod.init()
else:
mod.init("y") if sys.argv[1]=="y" else mod.init()
I soon discovered function if else doesn't work if argv[1] doesn't exist.
Use argparse, and make sure the default value of the command line argument is whatever the default value of mod.init's parameter is. You can make the argument optional and restrict it to a value of y.
When you run the script, you'll get an error if anything other than y is used for the option positional argument, so if mod.init is called at all, it will only be called with "y" or None as its argument.
import argparse
p = argparse.ArgumentParser()
p.add_argument("init_arg", choices=["y"], nargs='?', default=None)
args = p.parse_args()
mod.init(args.init_arg)

'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?

How can I make argparse apply type conversion to default value of positional arguments?

argparse applies type conversion to arguments of options, and to the default values of these if the default values are strings. However, it seems it doesn't do so for positional arguments:
import argparse as ap
p = ap.ArgumentParser()
p.add_argument('file', nargs='*',
metavar='FILE',
default='-',
type=ap.FileType(),
help='Input files. - is stdin. Default: %(default)s')
print(p.parse_args([]))
# Namespace(file='-')
print(p.parse_args(['-']))
# Namespace(file=[<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>])
(Ideone)
If I change file to --file so that these are option arguments, the default value is converted as expected.
Do I have any options better than explicitly passing argparse.FileType()('-') as the default?
The values put into sys.argv are always str objects, because the underlying operating system construct is an array is C character pointers. You need type to convert them to some other Python type.
The value of default, however, is under no such restriction. You can use a value of any type you like for that keyword argument.
p.add_argument('file',
nargs='*',
metavar='FILE',
default=[sys.stdin],
type=ap.FileType(),
help='Input files. - is stdin. Default: standard input')
I modified the help; getting the value of repr(sys.stdin) isn't particular useful, and the user should not be confused by describing the default value rather than specifying an exact Python object.

how to pass mutually exclusive argument as a variable

I was learning to handle command line arguments in Python with argparse. While not mutually exclusive arguments can be passed as variables, it is not clear to me how to do the same for mutually exclusive arguments. In the following example, I'd like to print out all the arguments. First 2 is easy. However the third one is tricky, because '-a' and '-b' have different names of destination. Therefore the last 2 lines cannot exist in the code at the same time.
#/usr/bin/env python
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-t' dest='thread', help='gtdownload thread', default=4, type=int)
parser.add_argument('-n' dest='number', help='number of downloads', default=1, type=int)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-a', dest='analysis', help='analysis ID')
group.add_argument('-b', dest='barcode', help='barcode')
args = parser.parser_args()
print args.thread
print args.number
#???? how to print out mutually exclusive argument
print args.analysis
print args.barcode
Most of the tutorials about add_mutually_exlusive_group out there stop at parser.parser_args() and never say what to do with the mutually exclusive arguments afterwards. But it is very important to know how exactly can the mutually exclusive arguments be passed to the rest of the code.
if args.analysis is not None:
print args.analysis
if args.barcode is not None:
print args.barcode
By putting -a and -b in the group, all you are telling the parser is to raise an error if you use both options in the command line.
Print args, and you will see that both attributes are present in the Namespace. The group just ensures that one will have its default value (None). The other will have the value you gave in the command line. Otherwise those attributes are just like the other ones.
print args # a very useful statement when debugging argparse
(The group also affects the usage display).
You'd have to use default=argparse.SUPPRESS to keep an attribute out of the Namespace (unless given in the commandline).

Categories

Resources