Program quits without taking user input in argparse example - python

I am new to python. I tried to run below python code in pycharm but without taking user input it exits. Any help?
import math
import argparse
parse = argparse.ArgumentParser(description='calculate the area of a cylinder')
parse.add_argument('radius', type=int, help='Radius of the Cylinder')
parse.add_argument('height', type=int, help='Height of the Cylinder')
args = parse.parse_args()
def cylinder_volume(radius, height):
vol = math.pi * (radius ** 2) * (height)
return vol
if __name__ == '__main__':
print(cylinder_volume(args.radius, args.height))
age = input("take input")
print("The input is",age)
#C:\Users\manoj\venv\argparse_demo\Scripts\python.exe C:/Users/manoj/PycharmProjects/argparse_demo/new.py
#usage: new.py [-h] radius height
#new.py: error: the following arguments are required: radius, height
#Process finished with exit code 2

It seems quite a redundat use of both command line argument and input(). I think doing examples with input() take syou on a wrong path in python programming, they also make bad question of StackOverflow with undetermined/unreplicable results. I was trying to make this point here earlier, but with very limited support from community.
In this particular case the line swith input seem very redundant. You just seem to learn passing the arguments through command line and then you want to play with input() - which seems a step back.

argparse takes only sys.argv arguments. To use argparse, you need to specify your arguments through command line, like: python new.py argument1 argument2
If you want to use input() for interactive purposes, pass the return value of input() to your function and don't use argparse.

Related

How do I suppress an argument when nothing is input on command line?

#!/usr/bin/env python3
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--selection', '-s')
parser.add_argument('--choice', '-c', default = argparse.SUPPRESS)
args = parser.parse_args()
def main(selection, choice):
print(selection)
print(choice)
if __name__=='__main__':
main(args.selection, args.choice)
The example provided is just to provide something simple and short that accurately articulates the actual problem I am facing in my project. My goal is to be able to ignore an argument within the code body when it is NOT typed into the terminal. I would like to be able to do this through passing the argument as a parameter for a function. I based my code off of searching 'suppress' in the following link: https://docs.python.org/3/library/argparse.html
When I run the code as is with the terminal input looking like so: python3 stackquestion.py -s cheese, I receive the following error on the line where the function is called:
AttributeError: 'Namespace' object has no attribute 'choice'
I've tried adding the following parameter into parser like so:
parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
I've also tried the above with
parser.add_argument('--choice', '-c')
But I get the same issue on the same line.
#Barmar answered this question in the comments. Using 'default = None' in parser.add_argument works fine; The code runs without any errors. I selected the anser from #BorrajaX because it's a simple solution to my problem.
According to the docs:
Providing default=argparse.SUPPRESS causes no attribute to be added if the command-line argument was not present:
But you're still assuming it will be there by using it in the call to main:
main(args.selection, args.choice)
A suppressed argument won't be there (i.e. there won't be an args.choice in the arguments) unless the caller specifically called your script adding --choice="something". If this doesn't happen, args.choice doesn't exist.
If you really want to use SUPPRESS, you're going to have to check whether the argument is in the args Namespace by doing if 'choice' in args: and operate accordingly.
Another option (probably more common) can be using a specific... thing (normally the value None, which is what argparse uses by default, anyway) to be used as a default, and if args.choice is None, then assume it hasn't been provided by the user.
Maybe you could look at this the other way around: You want to ensure selection is provided and leave choice as optional?
You can try to set up the arguments like this:
parser = argparse.ArgumentParser()
parser.add_argument('--selection', '-s', required=True)
parser.add_argument('--choice', '-c')
args = parser.parse_args()
if __name__ == '__main__':
if args.choice is None:
print("No choice provided")
else:
print(f"Oh, the user provided choice and it's: {args.choice}")
print(f"And selection HAS TO BE THERE, right? {args.selection}")

Get user input with arguments in Python

TL;DR I need to get a user input that contains an argument in order to do something, I need my own script that gets user input, and acts like it's its own interpreter.
My goal is to make my own CLI with my own commands.
What I need now is to get user input within a python script. The grammar for my CLI is below: (The thing I don't know how to do)
COMMAND + ARGUMENT1 + ARGUMENT2 + ARGUMENT3
Example of what I want to do:
say "hi this is a test"
hi this is a test
I have a plan for how I can make the commands with arguments,
I make a folder named 'bin' and I put python scripts in them.
Inside the python scripts are functions.
Depending on the command type, either I call the functions do do something, or it prints a output.
But for now, I need to know HOW to get user input with ARGUMENTS
The built-in argparse module as #ToTheMax said can create complex command line interfaces.
By default argparse.ArgumentParser.parse_args() will read the command line arguments to your utility from sys.argv, but if you pass in an array, it will use it instead.
You can lex (split into an array of "words") a string just like the shell is using shlex.split() which is also built in. If you use quotation marks like in your example, the words between them won't be split apart, just as in the shell.
Here's a complete example. Refer to the documentation, because this is a bit of an advance usage of argparse. There is a section that talks about "subcommands" which is what this example is based on.
import argparse
import shlex
def do_say(args):
print(args.what)
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
say_command = subparsers.add_parser('say')
say_command.add_argument('what')
say_command.set_defaults(func=do_say)
command = 'say "hi this is a test"'
args = parser.parse_args(shlex.split(command))
args.func(args)
The cmd module is another built-in way to make a command prompt, but it doesn't do the parsing for you, so you'd maybe combine it with argparse and shlex.
I realize I already have a question that is answered.
You can find it here:
How do you have an input statement with multiple arguments that are stored into a variable?
Here is the correct code:
def command_split(text:str) -> (str,str):
"""Split a string in a command and any optional arugments"""
text = text.strip() # basic sanitize input
space = text.find(' ')
if space > 0:
return text[:space],text[space+1:]
return text,None
x = input(":>")
command,args = command_split(x)
# print (f'command: "{command:}", args: "{args}"')
if command == 'echo':
if args == None:
raise SyntaxError
print (args)
A more simple way:
x = input(":>")
if x.split(" ")[0] == 'echo':
echoreturn = ' '.join(x.split(" ")[1:])
print(echoreturn)
My version to #rgov 's post: (Thank you!)
import argparse
import shlex
def do_say(args):
print(args.what)
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
say_command = subparsers.add_parser('say')
say_command.add_argument('what')
say_command.set_defaults(func=do_say)
while True:
try:
command = input(":>")
args = parser.parse_args(shlex.split(command))
args.func(args)
except SyntaxError:
print("Syntax Error")
except ValueError:
print("Value Error")
except:
print("")

new to argParse, not sure where my error is

I am completely new to Python, just started today and getting to grips with Python. Running it in Visual Studio btw.
Came across the import argParse and this is where things got a bit confusing for me.
I have some code I'm trying to get to work but it won't and I am quite clueless.
I'm getting an error on the code args = parser.parse_args() and I have no idea why either. Code is below
import math
import argparse
parser = argparse.ArgumentParser(description='calculate')
parser.add_argument('radius', type=int, help="radius plzz")
parser.add_argument('height', type=int, help="height plzz")
args = parser.parse_args()
def cylinder_volume(radius, height):
vol = (math.pi) * (radius ** 2) * height
return vol
if __name__ == '__main__':
print(cylinder_volume(args.radius, args.height))
I do have an idea of what's going on in this code but I don't know why it won't run as expected?
Maybe because I'm using Visual Studio? Maybe I need to import something else..
I have an image of the error!
args = parser.parse_args() parses the command line arguments (accessible as the sys.argv list) and makes the first argument args.radius and the second argument args.height, per the calls to the add_argument method. So all you need to do is to run the script from the command line with two integer arguments, e.g.:
script_name.py 123 456
or to test it in an IDE such as Visual Studio, you can pass a list of arguments to parse_args instead:
args = parser.parse_args(['123', '456'])
which outputs:
21673294.79680895
you can add 'dest=(str)' to send the argument as an attribute of args.
parser.add_argument(
'radius',
type=int,
help="radius plzz",
dest='radius'
)
parser.add_argument(
'height',
type=int,
help="height plzz",
dest='height'
)
Then you can call the arguments as you did in:
print(cylinder_volume(args.radius, args.height))

Simple sort program from the command line

I am trying to prevent this simple sort program to accept only 1 argument when printing in reverse. this is what I type and it still goes thru:
python sort.py alpha -r
here is my whole program:
example: python sort.py able spencer delta
to reverse:
python sort.py -r able spencer delta
python sort.py --reverse able spencer delta
import argparse
import sys
def wordsorter():
argparser = argparse.ArgumentParser()
argparser.add_argument('user_string', nargs='*')
argparser.add_argument("-r","--
reverse",action="store_true",default="False",dest="z_to_a")
args = argparser.parse_args()
if (len(sys.argv)==1 or len(sys.argv)==2):
print("Invalid command line arguments to program. Please, supply two or more strings to sort.")
sys.exit(1)
if args.z_to_a == True and len(sys.argv)>1:
words_to_sort= sorted(args.user_string, reverse = True)
print(*words_to_sort)
print("if 1")
else:
words_to_sort = sorted(args.user_string)
print(*words_to_sort)
print("if 2")
if __name__ == '__main__':
wordsorter ()
When I enter one Argument without sorting in reverse it works
If I try to use reverse with one argument it should not work.
What am I doing wrong?
Your problem is caused by the fact that you tell argparse to expect any number of arguments for user_string instead of at least two, and then check that len(sys.argv) >= 2 (by the way, this is a better way to write that if condition), but it can be equal to 2 if you pass -r and only one argument for user_string.
You can check that len(args.user_string) >= 2 and that should work.
If you want to do it through argparse: Unfortunately, while it is possible to tell it to expect at least one argument, it is not possible to directly tell it to expect at least two. A possible workaround is described in this answer.

How to make a python script work with and without arguments (default arguments)?

I am trying to get a Python script to work regardless when an argument has been passed or not.
The goal is to make the script functional as "MyPython.py" and "MyPython.py 5" should be able to work. If no argument has been passed, then the argument should be 0.
The variable imported_number should by default be 0 but if an argument has been detected, then it should take whatever number the user has passed.
import argparse
imported_number=0
parser = argparse.ArgumentParser()
parser.add_argument("opt_number", type=int, help="Provide a number please")
args = parser.parse_args()
if args.opt_number > 0:
imported_number=args.opt_number
print "You provided me with the number " + imported_number
print "You provided me with the number {}".format(args.opt_number)
else:
print "You did not provide me with any number. Taking the default value, which is " + imported_number
Unfortunately I am getting the error: too few arguments error message.
Does anyone know of good and automated methods to get this task done? I'd appreciate it.
Use nargs, default, const like this:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("opt_number", type=int, help="Provide a number please",
nargs='?', default=0, const=0)
args = parser.parse_args()
print(args)
Your opt_number will be initialized with 0 when no argument is provided.
You can make your script a function that accepts and argument passed to it.
import sys
def your_function(imported_number=0):
#your code
if __name__=='__main__':
try:
imported_number=sys.argv[1]
except:
pass
your_function(imported_number)

Categories

Resources