I have written a python function which takes multiple arguments and i want it to run from terminal but it's not working. what am I doing wrong?
counting.py script:
def count (a, b):
word = False
a = " " + a + " "
b = " " + b + " "
result = 0
for i in range (len (a)-1):
if a[i] == " " and a[i+1] != " ":
word = True
result += 1
else:
word = False
for i in range (len (b)-1):
if b[i] == " " and b[i+1] != " ":
word = True
result += 1
else:
word = False
return result
if __name__ == "__main__":
count (a, b)
terminal command:
python counting.py count "hello world" "let's check you out"
useing sys model,
add this code, the sys.argv first parameter is this file name
import sys
if __name__ == "__main__":
a = sys.argv[1]
b = sys.argv[2]
count(a,b)
terminal command:
python counting.py "hello word" "let's check you out"
ex:
import sys
def count(s1, s2):
print s1 + s2
print sys.argv
count(sys.argv[1], sys.argv[2])
out:
python zzzzzzz.py "hello" "word"
['zzzzzzz.py', 'hello', 'word']
helloword
a and b are the arguments of count. You cannot use them outside that scope. You could instead use sys.argv to access the commandline arguments:
from sys import argv
if __name__ == "__main__":
print(count (argv[1], argv[2]))
As suggested by others using sys:
from sys import argv
def count(a, b):
return len(a.split(" ")) + len(b.split(" "))
if __name__ == "__main__":
a = argv[1]
b = argv[2]
word_count = count(a, b)
print(word_count)
Or, you could use the built-in module argparse. In case you ever have a more complex script taking arguments from the console.
import argparse
def count(a, b):
return len(a.split(" ")) + len(b.split(" "))
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Word Count")
parser.add_argument("-a", type=str, help="First Sentence")
parser.add_argument("-b", type=str, help="Second Sentence")
args = parser.parse_args()
word_count = count(args.a, args.b)
print(word_count)
Execute your script with python counting.py -a "hello world" -b "let's check you out".
And if you execute python counting.py -h, you'll get a nicely formatted help for the users:
usage: counting.py [-h] [-a A] [-b B]
Word Count
optional arguments:
-h, --help show this help message and exit
-a A First Sentence
-b B Second Sentence
Related
Im trying to start this script with a argument.
When i start the script from a terminal i want to type "python test.py C:\Users\etc\etc\log.log count" to run func1 or error to run func3.
I have try to play around with sys.argv / sys.argv[2] but i cant get it to work.
import sys
def func1():
count = 0
with open(r'C:\Users\etc\etc\log.log') as logfile:
lines = logfile.readlines()
for error in lines:
count += error.count('[error]')
print('errors', count)
def func3():
import re
with open(r'C:\Users\etc\etc\log.log') as logfile:
for line in map(str.strip, logfile):
m = re.findall('\[.*?\]', line)
if len(m) > 1 and m[1] in ('[error]'):
offset = line.find(m[1]) + len(m[1]) + 1
print(m[0], line[offset:])
if __name__ == '__main__':
func1()
func3()
sys.argv is a list containing the arguments passed to the program. The first item is the file name, the rest are the arguments so to get the first argument you use sys.argv[1].
Because the first argument isn't necessarily provided, I've used a try/except block to catch the possible IndexError. You can handle this however you like.
You can then just use an if statement to decide which function to run.
import sys
def func1():
count = 0
with open(r'C:\Users\etc\etc\log.log') as logfile:
lines = logfile.readlines()
for error in lines:
count += error.count('[error]')
print('errors', count)
def func3():
import re
with open(r'C:\Users\etc\etc\log.log') as logfile:
for line in map(str.strip, logfile):
m = re.findall('\[.*?\]', line)
if len(m) > 1 and m[1] in ('[error]'):
offset = line.find(m[1]) + len(m[1]) + 1
print(m[0], line[offset:])
if __name__ == '__main__':
try:
arg = sys.argv[1]
except: pass
else:
if arg == "count":
func1()
elif arg == "error":
func3()
I have the following Python code that has 1 command line optional parameter (c) that has an argument and 2 options (a and b) that do not have an argument:
import sys, getopt
def main(argv):
inputfile = ''
outputfile = ''
try:
opts, args = getopt.getopt(argv,"abc:",["csvfile="])
except getopt.GetoptError:
print 'Error in usage - a does not require an argument'
sys.exit(2)
for opt, arg in opts:
print "Raw input is: {}" .format(opt)
if opt in ("-c", "--csvfile"):
outputfile = arg
print 'Output file is {}' .format(outputfile)
elif opt == '-a':
print 'Alpha'
elif opt == '-b':
print 'Beta'
print 'User choice is {}' .format(opt.lstrip('-'))
if __name__ == "__main__":
main(sys.argv[1:])
When I enter python readwritestore.py -a I get:
Raw input is: -a
Alpha
User choice is a
This is what I was hoping for if the commandline argument is -a. However, if I enter python readwritestore.py -a csvfile_name, then I get:
Raw input is: -a
Alpha
User choice is a
This is not what I intended for. In this function, c is the only option that rquires an argument. If I enter a with an argument,
the code should give the error message that I set up
Error in usage - a does not require an argument
This does not happen for a or b. It is allowing the argument to be entered without raising an error.
If the options that do not require an argument are entered with an argument, then I would like it to raise an error. python readwritestore.py -a text
and python readwritestore.py -b text should raise the error Error in usage - a does not require an argument.
Is there a way to specify this? Is getopt() the correct way to do this?
Additional Information:
I only want python readwritestore.py -c text to work with the argument. For the other 2 options, a and b, the code should raise the error.
checking the size of sys.argv (the list of argument supplied when calling the script) can help you checking that :
import sys
import getopt
def main(argv):
inputfile = ''
outputfile = ''
opts, args = getopt.getopt(argv, "abc:", ["csvfile="])
for opt, arg in opts:
print "Raw input is:", opt
if opt in ("-c", "--csvfile"):
outputfile = arg
print 'Output file is ', outputfile
elif opt == '-a':
if len(sys.argv)=2:
print 'Alpha'
else:
print "incorect number of argument"
elif opt == '-b':
if len(sys.argv)=2:
print 'Beta'
else:
print "incorect number of argument"
print 'User choice is ', opt
if __name__ == "__main__":
main(sys.argv[1:])
I know it's not what you asked (argparse) but here is how you could do it with argparse :
from argparse import *
def main():
parser = ArgumentParser()
parser.add_argument('-c', '--csvfile', help='do smth with cvsfile')
parser.add_argument(
'-a', '--Alpha', help='Alpha', action='store_true')
parser.add_argument(
'-b', '--Beta', help='beta smth', action='store_true')
if args.csvfile:
print 'Output file is {}' .format(args.csvfile)
if args.Alpha:
print 'Alpha'
if args.Beta:
print 'Beta'
if __name__ == "__main__":
main()
It will raise an error is to many argument are supplied. (also python readwritestore.py -h will display the help just like man in unix)
I'm making an interpreter, and I have a function called parse(). The parse function returns some output.
I'm making a command that prints two command's outputs on the same line instead of on separate lines.
I have the following code:
def print_command2(command):
command = command.split("_") # The underscore separates the two commands
command[0] = command[0].strip("! ") # The command is !
print(parse(command[0])), # This should print the output of the first command
print(parse(command[1])) # And this should print the second
I typed in the following command to test it:
! p Hello_p World
(p is the equivalent of Python's print command.)
But it outputs the following:
Hello
World
I want it to print this:
HelloWorld
What's wrong?
EDIT: The answer from this question prints the following:
Hello
World
So it doesn't work as wanted.
EDIT: Here's the parse function. Please don't mind the terrible code.
def parse(command):
"""Parses the commands."""
if ';' in command:
commands = command.split(";")
for i in commands:
parse(i)
if '\n' in command:
commands = command.split('\n')
for i in commands:
parse(i)
elif command.startswith("q"):
quine(command)
elif command.startswith("p "):
print_command(command)
elif command.startswith("! "):
print_command2(command)
elif command.startswith("l "):
try:
loopAmount = re.sub("\D", "", command)
lst = command.split(loopAmount)
strCommand = lst[1]
strCommand = strCommand[1:]
loop(strCommand, loopAmount)
except IndexError as error:
print("Error: Can't put numbers in loop")
elif '+' in command:
print (add(command))
elif '-' in command:
print (subtract(command))
elif '*' in command:
print (multiply(command))
elif '/' in command:
print (divide(command))
elif '%' in command:
print (modulus(command))
elif '=' in command:
lst = command.split('=')
lst[0].replace(" ", "")
lst[1].replace(" ", "")
stackNum = ''.join(lst[1])
putOnStack(stackNum, lst[0])
elif command.startswith("run "):
command = command.replace(" ", "")
command = command.split("run")
run(command[1])
elif command.startswith('#'):
pass
elif command.startswith('? '):
stackNum = command[2]
text = input("input> ")
putOnStack(text, stackNum)
elif command.startswith('# '):
stackNum = command[2]
print(''.join(stack[int(stackNum)]))
elif command.startswith("."):
time.sleep(2)
else:
print("Invalid command")
return("")
TL;DR: I'm calling two functions. I want their output to print on the same line.
the print() function has extra arguments you can pass to it. You are interested in end.
def test1():
print('hello ', end='')
def test2():
print('there', end='')
test1()
test2()
>>>
hello there
>>>
It doesn't matter how many functions this comes from
I have written an application in Python to work with strings, i made a menu prompt from which i can select an operation to do, i tested all the functions, they work well, except the menu and main functions, that when i enter my choice nothing happens. Here's the code:
import re
import os
def searchInFile(searched, file):
try:
f = open(file)
except IOError.strerror as e:
print("Couldn't open the file: ", e)
else:
sea = re.compile(searched, re.IGNORECASE)
for line in f:
if re.search(sea, line):
print(line, end='')
def validateWithPattern(string):
patt = re.compile('([a-z0-9-_.])+#([a-z]+.)([a-z]{2,3})', re.IGNORECASE)
if re.search(patt, string):
print("Valid")
else:
print("Not valid!")
def menu():
print("|================MENU=================|\n", end='')
print("|0- Exit the program |\n", end='')
print("|1- Validate mail address |\n", end='')
print("|2- Search a string in a file |\n", end='')
print("|=====================================|\n", end='')
b = input("->")
return b
def main():
b = 10
while b != 0:
b = menu()
if b == 1:
a = input('Enter you mail address: ')
validateWithPattern(a)
elif b == 2:
a = input('Enter the file name: ')
c = input('Enter the string: ')
searchInFile(c, a)
elif b == 0:
os.system("PAUSE")
else: print("Choice error")
if __name__ == "__main__":
main()
Your b variable you are returning from menu function is a string, not an integer, so you can't compare it with numbers (input is automatically saved as string). If you use return int(b) instead of return b, it will be ok.
Also, I think your else: print("Choice error") should be indented the same way your if and elif are, since you probably want to write "Choice error" only if b is not one of given choices. The way it is indented in your code will print "Choice error" after the while loop ends and it will not print that message if you input the value it can't recognize (for example 3).
I am trying to create a program in python and my biggest problem is getting it to use command line options to assign the variables in the program. I have been using getopt and it will print from where I define it, but the variables can not be called upon outside of the definition so that I can use for the rest of my program.
In the code below, the print state for the "Is the following correct" comes out fine but if I try to print the gender or any other variable after the code, I just get an error that it isn't defined.
By the way, the options I run are: spice.py -g m -n 012.345.6789 -r 23 -e 13 -o voicemail.mp3
Code:
import sys
import getopt
def main(argv):
gender = 'missing'
phone = 'missing'
reasons = 'missing'
endings = 'missing'
output = 'missing'
try:
opts, args = getopt.getopt(argv, "hg:n:r:e:o:")
except getopt.GetoptError:
print 'spice.py -g <gender> -n <phone number> -r <reasons> -e <endings> -o <output name>'
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print 'test.py -i <inputfile> -o <outputfile>'
sys.exit()
elif opt in ("-g"):
gender = arg
elif opt in ("-n"):
phone = arg
elif opt in ("-r"):
reasons = arg
elif opt in ("-e"):
endings = arg
elif opt in ("-o"):
output = arg
print "Is the following correct? " + "Gender: " + gender + ", " + "Phone Number: " + phone + ", " + "Reasons: " + reasons + ", " + "Endings: " + endings + ", " + "Output: " + output
if __name__ == "__main__":
main(sys.argv[1:])
print gender
in your code, gender is not global. it's only in context within the function.
as proof, change the first couple of lines to:
import sys
import getopt
gender = 'missing'
def main(argv):
global gender
# ... all the same
# ... below here
and you'll now see that it prints (assuming it was working in context as you describe).
when you refactor you'll actually want to either write functions that return the values you want to use and then use them or create global variables and clean up the code a bit.