Using Argparse to create required argument with multiple options? - python

If I understand Argparse correctly, the positional arguments are the required arguments that the user can specify. I need to create a positional argument with argparse where the user can specify a certain type of argument that is displayed if he/she brings up the -h option. I've tried using add_argument_group but it simply only displays a header with a description of the other arguments when you bring up the -h option.
def Main():
parser = argparse.ArgumentParser(description = __doc__, formatter_class = argparse.RawDescriptionHelpFormatter)
parser.add_argument("input_directory",help = "The input directory where all of the files reside in")
sub_parser = parser.add_argument_group('File Type')
sub_parser.add_argument(".txt",help = "The input file is a .txt file")
sub_parser.add_argument(".n12",help = "The input file is a .n12 file")
sub_parser.add_argument(".csv",help = "The input file is a .csv file")
parser.parse_args()
if __name__ == "__main__":
Main()
So when I run the script, I should specify in order to run the script. If I choose either .txt, .n12, or .csv as my argument, then the script should run. However, if the I don't specify the file type from those 3 options listed, then the script wouldn't run.
Is there an argparse function that I'm missing that can specify multiple options for a positional argument?

Use the choices= parameter to force the user to choose from a restricted set of values.
import argparse
def Main():
parser = argparse.ArgumentParser()
parser.add_argument("input_directory",help = "The input directory where all of the files reside in")
parser.add_argument("file_type", help = "File Type", choices=['.txt', '.n12', '.csv'])
ns = parser.parse_args()
print(ns)
if __name__ == "__main__":
Main()

I think you're making this too complicated. If I understand your problem correctly, you want the user to enter two arguments: a directory name and a file type. You application will accept only three values for file type. How about simply doing this:
import argparse
def Main():
parser = argparse.ArgumentParser(description = __doc__, formatter_class = argparse.RawDescriptionHelpFormatter)
parser.add_argument("input_directory", help = "The input directory where all of the files reside in")
parser.add_argument("file_type", help="One of: .txt, .n12, .csv")
args = parser.parse_args()
print(args)
if __name__ == "__main__":
Main()
... and adding application logic to reject invalid values for file type.
You access the user-entered values through the object returned by parse_args().

Use option grouping feature use add_mutually_exclusive_group() instead of add_argument_group()
import argparse
def Main():
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("input_directory", help="The input directory where all of the files reside in")
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("-txt", action='store_true', help="The input file is a .txt file")
group.add_argument("-n12", action='store_true', help="The input file is a .n12 file")
group.add_argument("-csv", action='store_true', help="The input file is a .csv file")
print parser.parse_args()
if __name__ == "__main__":
Main()

Related

Store argparse input to use as variable

I am using argparse to require input from the user for a hardware id to then be called later on, I cannot work out how to get it so the user types
<command> --id <id>
Please help me see where I'm going wrong! Thanks
parser = argparse.ArgumentParser(description='Return a list of useful information after specifying a hardare/asset ID')
parser.add_argument('--id', type=str, required=True, help ='A hardware/asset id to provide information on')
args = vars(parser.parse_args())
args = parser.parse_args()
def main():
hardware_id = hardware_id_input
host = get_host_information(hardware_id)
print(host["hostname"])
print(host["hardware_id"])
Ditch the call to vars. You would have your argument stored as args.id after parsing. You would then call your main with the args.id as input.
Edit: added a code sample
def main(hw_id):
print(hw_id)
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description='Description.')
parser.add_argument('--id', type=str, help='The hardware id.', required=True)
args = parser.parse_args()
main(args.id)

I can "print(args.username) but I can't use args.username as a value for a search?

I have been trying to debug my program. I am accepting an argument for the username through argparse and want to use the args.username value to search the passwd file. I am getting the following error: NameError: name 'args' is not defined. I can do a print(args.username) but I can't use args.username in my search.
import argparse
# My argparse section
def main():
# initialize the parser
parser = argparse.ArgumentParser(description="my argparse script")
# add the parameters positional/optional
parser.add_argument('-u', '--username', nargs='+', help="Enter user name to search passwd file with", type=str)
# parse the arguments
args = parser.parse_args()
# This print statement works fine
print(args.username)
print(args)
# My search the passwd file section
# The statement below, user=args.username is causing the error
user = args.username
with open("passwd") as file:
for line in file:
if line.split(":")[0] == user:
print("User found : " + line.split(":")[0])
else:
print("User not found : " + line.split(":")[0])
if __name__ == '__main__':
main()
args is in the scope of main(). And, main() is running after your search code, since your search code is outside of any function. Since your search is outside of main's scope, it doesn't have access to args. You could un-indent the search so it'll be within scope, allowing you to use args. This will have the effect of running the search at the end of main() instead of before, so not only will args be defined, but it'll also be in scope:
import argparse
# My argparse section
def main():
# initialize the parser
parser = argparse.ArgumentParser(description="my argparse script")
# add the parameters positional/optional
parser.add_argument('-u', '--username', nargs='+', help="Enter user name to search passwd file with", type=str)
# parse the arguments
args = parser.parse_args()
# This print statement works fine
print(args.username)
print(args)
# My search the passwd file section
# The statement below, user=args.username is causing the error
user = args.username
with open("passwd") as file:
for line in file:
if line.split(":")[0] == user:
print("User found : " + line.split(":")[0])
else:
print("User not found : " + line.split(":")[0])
if __name__ == '__main__':
main()
You mentioned you could do print(args.username) in main() just fine, which seems like that'd only be possible if you removed your search code, since the search code would error before main() even ran in the code you've shown. So I'm thinking your example isn't the code in which that print worked.

argparse - is it possible for user to enter argument not in one line?

I am new with this argparse module.
import argparse
parser = argparse.ArgumentParser(description='Input & Output Files')
parser.add_argument('indir', type=str, help='Input File Path')
parser.add_argument('outdir1', type=str, help='Output File Path 1')
parser.add_argument('outdir2', type=str, help='Output File Path 2')
parser.add_argument('outdir3', type=str, help='Output File Path 3')
args = parser.parse_args()
print(args.indir)
Here is my code to get input and output. Below is how user should write to run my code including given input & output.
python3.7.4 test.py /input /output1 /output2 /output3
I would like to ask if it is possible if i can asked the user to enter the input & output one by one as the arguments have a very long path. For example maybe the user can type input first the followed by output1, output2 and output3.
It's not exactly that what you looked for, but there is a package called click (“Command Line Interface Creation Kit”). It offers the ability to prompt the user for input. Maybe thats a nicer way for very long paths.
A small example for your use case:
import click
#click.command()
#click.option('--indir', prompt='Input File Path', help='Input File Path', type = str, required = True)
#click.option('--outdir1', prompt='Output File Path 1', help='Output File Path 1', type = str, required =True)
def test(indir, outdir1):
click.echo(indir)
click.echo(outdir1)
if __name__ == '__main__':
test()
In the CLI you get prompted to insert your paths step by step. You can also access the help page like in argparse.

How to specify the directory using python argparser?

In my python script,i need to read the input ".csv files" from the Input directory(/home/ubuntu/pythontraining/InputCsv) and store the result in two separate output directories i.e,StudentDetails(/home/ubuntu/pythontraining/StudentDetails) and FacultyDetails(/home/ubuntu/pythontraining/FacultyDetails).I want to specify the directory path as a command line arguments using argparser.Can someone help me how to specify the directory path as a command line arguments using python's argparser?
import argparse
parser=argparse.ArgumentParser()
parser.add_argument("Input_directory")
parser.add_argument("Student_directory")
parser.add_argument("Faculty_directory")
You can try below example -
import argparse
def some_args():
parser = argparse.ArgumentParser(description='Some description')
parser.add_argument('--input-dir', help='Input directory')
parser.add_argument('--student-dir', help='Input Student directory')
parser.add_argument('--faculty-dir', help='Input Faculty directory')
return parser.parse_args()
def main():
args = some_args()
input_path = args.input_dir
student_path = args.student_dir
faculty_path = args.faculty_dir
print (input_path ) #prints your input_path which you passed
print (student_path ) #prints your student_path which you passed
print (faculty_path ) #prints your faculty_path which you passed
if __name__ == '__main__':
main()
Command line argument to be as -
python foo.py --input-dir <some_arg> --student-dir <some_arg> --faculty-dir <some_arg>
Reference
https://docs.python.org/3/howto/argparse.html

How to use python argparse with conditionally optional arguments?

Here is the current code.
import time
import collections
from modules import outputs
from modules import scrub
from modules import lookups
parser = argparse.ArgumentParser(description='AppMap Converter to Generate Asset Files from AppMapp Data')
parser.add_argument("operation", nargs='?', default="empty", help='The operation to perform')
parser.add_argument("input", nargs='?', default="empty", help='The input AppMapp File Path')
parser.add_argument("output", nargs='?', default="empty", help='The output Asset File Path')
args = parser.parse_args()
start = time.time()
if(args.operation == "Convert"):
input_file_path = args.input
output_file_path = args.output
#DO LOTS OF STUFF
else:
exit()
The script is called sacsproc, so I run it from the command line as follows:
./sacsproc Convert input.csv output.csv
This all works nicely, the problem is that I need more sacsproc commands which may have a totally different set of secondary parameters. i.e. one command might be:
./sacsproc Clean -rts input.csv output.csv err.csv
Thus, I am trying to determine how one defines arguments that are conditional on the first argument? In my mind, I'm thinking about the zfs command line utilities that do what I am trying to do (e.g. zpool create mirror sdb sdc vs. zpool remove sda).
use subparsers
subparsers = parser.add_subparsers(help="sub-command help")
group1 = subparsers.add_parser("something",help="do something")
group1.set_defaults(which="g1") # some default value (so you know which group was activated)
group1.add_argument("ARG",help='do something on ARG')
group2 = subparsers.add_parser("other",help="do something else")
group2.set_defaults(which="g2") # give some default value
group2.add_argument("ARG",help='do something else on ARG')
ok ...
import argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help="sub-command help")
g1 = subparsers.add_parser("thing1",help="bind to a port and just echo back anything it gets ... with a prompt")
g1.set_defaults(which="g1")
g1.add_argument("input",help='the input file')
g1.add_argument("output",help='the output file')
g2 = subparsers.add_parser("thing2",help="create a bridge between two ports, this is useful for generating a logfile")
g2.set_defaults(which="g2")
g2.add_argument("input",help='thie input file')
g2.add_argument("output",help='the output file')
g2.add_argument("error",help="the err file")
def print_help(args):
print "ARGS:",args
try:
parser.parse_args(args)
except:
print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n"
print_help(["-h"])
print_help(["thing1","-h"])
print_help(["thing2","-h"])

Categories

Resources