Let´s say I execute a python file like a program in Ubuntu
python filename.py --input1 --input2
How can I use those 2 inputs in my code? (If even possible with python)
BTW I would like to do this on Windows, not Linux.
For example, my code contains a function that takes 1 argument, in form of a string.
I could just do that argument input as input() while the code is running, but I would like to specify it when I execute the code already.
I recommend you take a look at argparse. https://docs.python.org/3.7/howto/argparse.html
Or
$ python
>>> import argparse
>>> help(argparse)
This is certainly possible and in fact even bread and butter in python and other script languages.
In python there is even the getopt module that helps you with that if you are familiar with the c implementation.
Copy-paste from official python documentation:
import getopt, sys
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
except getopt.GetoptError as err:
# print help information and exit:
print str(err) # will print something like "option -a not recognized"
usage()
sys.exit(2)
output = None
verbose = False
for o, a in opts:
if o == "-v":
verbose = True
elif o in ("-h", "--help"):
usage()
sys.exit()
elif o in ("-o", "--output"):
output = a
else:
assert False, "unhandled option"
# ...
if __name__ == "__main__":
main()
Official documentation is here: https://docs.python.org/2/library/getopt.html
For tutorials, see for example: https://www.tutorialspoint.com/python/python_command_line_arguments.htm
On the other hand argparse is easier if you like to get it done in an easier but not c-like way. For that, see the other answer.
For a simple case, you can just use sys.argv as follows:
# in your source.py
from sys import argv
arg1 = argv[1] # If your input is a "numerci type" , apply the the appropriate
arg2 = argv[2] # conversion by using (int, float)
...
Then you can execute your code, by:
python source.py arg1 arg2
Related
I would like to create a simple python script that will take a parameter from the console, and it will display this parameter. If there will be no parameter then I would like to display error message, but custom message not something like IndexError: list index out of range
Something like this:
if isset(sys.argv[1]):
print sys.argv[1];
else:
print "No parameter has been included"
if len(sys.argv) >= 2:
print(sys.argv[1])
else:
print("No parameter has been included")
For more complex command line interfaces there is the argparse module
in Python's standard library - but for simple projects taking just a couple parameters directly checking sys.argv is alright.
update as of 2019, the recomendation is to use the external library "click", as it provides very "Pythonic" ways of including complex documents in a way they are easily documented.
You can check the lenght
if len(sys.argv) > 1:
...
Or the try/except
try:
sys.argv[1]
except IndexError as ie:
print("Exception : {0}".format(ie))
import sys
try:
print sys.argv[1]
except IndexError:
print "No parameter has been included"
import sys
print sys.argv[0] # will print your file name
if len(sys.argv) > 1:
print sys.argv[1];
else:
print "No parameter has been included"
OR
import sys
try:
print sys.argv[1]
except IndexError, e:
print "No parameter has been included"
Just for fun, you can also use getopt which provides you a way of predefining the options that are acceptable using the unix getopt conventions.
import sys
import getopt
try:
opts, args = getopt.getopt(sys.argv[1:], "hvxrc:s:", ["help", "config=", "section="])
except getopt.GetoptError as err:
print ("Option error:", str(err))
opts=[]
for op , val in opts:
print ("option",op,"Argument",val)
if not opts:
print ("No parameter supplied")
In the above if an incorrect parameter is supplied all of the options are scrapped.
Examples of use would be:
python myprog.py -h
python myprog.py --help
python myprog.py -c123
python myprog.py --config=123
https://pymotw.com/2/getopt/
http://linux.about.com/library/cmd/blcmdl1_getopt.htm
without exception model using if else short hand, in single line we can read args
args = sys.argv
env = args[1:] and args[1] or None
username = args[2:] and args[2] or None
password = args[3:] and args[3] or None
I have a following simple code:
import sys, getopt
ifile=''
ofile=''
try:
opts, args = getopt.getopt(sys.argv[1:],"h:i:o:")
except getopt.GetoptError as e:
print (str(e))
print("test.py -i input -o output")
sys.exit(2)
for o, a in opts:
if o == '-h':
print 'test.py -i input -o output'
sys.exit()
elif o == '-i':
ifile=a
elif o == '-o':
ofile=a
What should I need to add, if I want to print error (and also help) message 'test.py -i input -o output' when I execute just the script like:
$ python test.py
Thank you
You can write
if len(sys.argv) <= 1:
print('test.py -i input -o output')
exit(1)
after the imports, which basically means that if i don't have any arguments, print the message and quit running the script.
Just as an alternative, if you are interested, the documentation for getopts actually provides a suggestion to use argparse, which significantly reduces the lines of code you have to write to handle arguments.
Look at the bottom of the doc here:
https://docs.python.org/2/library/getopt.html#getopt.GetoptError
And here is the documentation for argparse
https://docs.python.org/2/library/argparse.html#module-argparse
The big bonus with argparse is that has a built in "help" that is nicely formatted. Look at the following example. You can take this code and test on your end too.
from argparse import ArgumentParser, RawTextHelpFormatter
parser = ArgumentParser(
description='This application will perform actions',
formatter_class=RawTextHelpFormatter
)
parser.add_argument(
'-i',
help='Things with i',
)
parser.add_argument(
'-o',
help='Things with o',
)
args = vars(parser.parse_args())
if args.get('i'):
print(args.get('i'))
elif args.get('o'):
print(args.get('o'))
else:
parser.error('Invalid options provided')
Just thought I'd share as an alternative.
I need to write a command line application, like a shell. So it will include commands etc. The thing is I don't know how to pass parameters to the funcions in a module. For example:
User writes: function1 folder1
Program should now pass the 'folder1' parameter to the function1 function, and run it. But also it has to support other functions with different parameters ex:
User input: function2 folder2 --exampleparam
How to make this to work? I mean, I could just write a module, import it in python and just use the python console, but this is not the case. I need a script that takes command input and runs it.
I tried to use eval(), but that doesn't solve the problem with params. Or maybe it does but I don't see it?
The first part of your problem -- parsing the command line -- can be solved with argparse.
The second part -- converting the string name of a function into a function call -- can be done with exec or a dispatching dict which maps from strings to function objects.
I would recommend NOT using exec for this, since
allowing a user to call arbitrary Python functions from the command line might be dangerous. Instead, make a whitelist of allowable functions:
import argparse
def foo(path):
print('Running foo(%r)' % (path, ))
def bar(path):
print('Running bar(%r)' % (path, ))
dispatch = {
'foo': foo,
'bar': bar,
}
parser = argparse.ArgumentParser()
parser.add_argument('function')
parser.add_argument('arguments', nargs='*')
args = parser.parse_args()
dispatch[args.function](*args.arguments)
% test.py foo 1
Running foo('1')
% test.py bar 2
Running bar('2')
% test.py baz 3
KeyError: 'baz'
The above works when the command is typed into the command-line itself. If the command is being typed into stdin, then we'll need to do something a bit different.
A simple way would be to call raw_input to grab the string from stdin. We could then parse the string with argparse, as we did above:
shmod.py:
import argparse
def foo(path):
print('Running foo(%r)' % (path, ))
def bar(path):
print('Running bar(%r)' % (path, ))
dispatch = {
'foo': foo,
'bar': bar,
}
def parse_args(cmd):
parser = argparse.ArgumentParser()
parser.add_argument('function')
parser.add_argument('arguments', nargs='*')
args = parser.parse_args(cmd.split())
return args
main.py:
import shmod
while True:
cmd = raw_input('> ')
args = shmod.parse_args(cmd)
try:
shmod.dispatch[args.function](*args.arguments)
except KeyError:
print('Invalid input: {!r}'.format(cmd))
Another, more sophisticated way to handle this is to use the cmd module, as #chepner mentioned in the comments.
from cmd import Cmd
class MyInterpreter(Cmd):
prompt = '> '
def do_prompt(self, line):
"Change the interactive prompt"
self.prompt = line + ': '
def do_EOF(self, line):
return True
def do_foo(self, line):
print('Running foo {l}'.format(l=line))
def do_bar(self, line):
print('Running bar {l}'.format(l=line))
if __name__ == '__main__':
MyInterpreter().cmdloop()
For more information on how to use the cmd module, see Doug Hellman's excellent tutorial.
Running the code above yields a result like this:
% test.py
> foo 1
Running foo 1
> foo 1 2 3
Running foo 1 2 3
> bar 2
Running bar 2
> baz 3
*** Unknown syntax: baz 3
optparse is deprecated since python 2.7 and anyway argparse is much more flexible.
The approach of unutbu is safe, but in case you provide whitelist, I would suggest you to let the user know which functions are accepted
dispatch = {
'foo': foo,
'bar': bar,
}
parser = argparse.ArgumentParser()
parser.add_argument('function', choices=dispatch.keys() )
FYI: if the parsing is not too complicated, docopt looks like a very nice package
How about sys.argv? For more advanced stuff check out argsparse. optparse seems depreciated now, but there's a lot of answers here about this question.
Take a look at the optparse module in python. It's exactly what you would need:
http://docs.python.org/2/library/optparse.html
Or you can write your own custom opt-parser (minimalistic though)
def getopts(argv):
opts = {}
while argv:
if argv[0][0] == '-': # find "-name value" pairs
opts[argv[0]] = argv[1] # dict key is "-name" arg
argv = argv[2:]
else:
argv = argv[1:]
return opts
if __name__ == '__main__':
from sys import argv # example client code
myargs = getopts(argv)
# DO something based on your logic here
But in case your script needs to run on python 3 and beyond, you need to consider argparse module.\
Hope that helps.
Take a look at optparse . This can help passing and receiving shell style parameters to python scripts.
Update:
Apparently optparse is deprecated now and argparse is now preferred option for parsing command line arguments.
import sys
def main(arg):
return arg
print main(sys.argv[1])
where sys.argv[0] is the .py file you're running, and all the ones after it would be each argument. you could check the length of the list, then iterate through it, and parse them as necessary and pass the correct things to each function
I am trying to create a bash script which passes its own argument onto a python script. I want it to work like this.
If I run it as this:
script.sh latest
Then within the bash script it runs a python script with the "latest" argument like this:
python script.py latest
Likewise if the bash script is run with the argument 123 then the python script as such:
python script.py 123
Can anyone help me understand how to accomplish this please?
In this case the trick is to pass however many arguments you have, including the case where there are none, and to preserve any grouping that existed on the original command line.
So, you want these three cases to work:
script.sh # no args
script.sh how now # some number
script.sh "how now" "brown cow" # args that need to stay quoted
There isn't really a natural way to do this because the shell is a macro language, so they've added some magic syntax that will just DTRT.
#!/bin/sh
python script.py "$#"
In the pythonscript script.py use getopt.getopt(args, options[, long_options]) to get the arguments.
Example:
import getopt, sys
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
except getopt.GetoptError as err:
# print help information and exit:
print str(err) # will print something like "option -a not recognized"
usage()
sys.exit(2)
output = None
verbose = False
for o, a in opts:
if o == "-v":
verbose = True
elif o in ("-h", "--help"):
usage()
sys.exit()
elif o in ("-o", "--output"):
output = a
else:
assert False, "unhandled option"
# ...
if __name__ == "__main__":
main()
A very goo buit-in parser is argparse. Yo can use it as follows:
import argparse
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
const=sum, default=max,
help='sum the integers (default: find the max)')
args = parser.parse_args()
print(args.accumulate(args.integers))
In bash, arguments passed to the script are accessed with the $# notation (# being a number. Using $# exactly like that should give you the number of args passed). So if you wanted to pass arguments:
Calling the script:
`#script.sh argument`
Within the script:
python script.py "$1"
I am trying to pass '-f nameoffile' to the program when I call it from the command line. I got this from the python sites documentation but when I pass '-f filename' or '--file=filename' it throws the error that I didnt pass enough arguments. If i pass -h the programs responds how it should and gives me the help. Any ideas? I imagine its something simple that I am overlooking. Any and all help is great, thanks, Justin.
[justin87#el-beasto-loco python]$ python openall.py -f chords.tar
Usage: openall.py [options] arg
openall.py: error: incorrect number of arguments
[justin87#el-beasto-loco python]$
#!/usr/bin/python
import tarfile
import os
import zipfile
from optparse import OptionParser
def check_tar(file):
if tarfile.is_tarfile(file):
return True
def open_tar(file):
try:
tar = tarfile.open(file)
tar.extractall()
tar.close()
except tarfile.ReadError:
print "File is somehow invalid or can not be handled by tarfile"
except tarfile.CompressionError:
print "Compression method is not supported or data cannot be decoded"
except tarfile.StreamError:
print "Is raised for the limitations that are typical for stream-like TarFile objects."
except tarfile.ExtractError:
print "Is raised for non-fatal errors when using TarFile.extract(), but only if TarFile.errorlevel== 2."
def check_zip(file):
if zipfile.is_zipfile(file):
return True
def open_zip(file):
try:
zip = zipfile.ZipFile(file)
zip.extractall()
zip.close()
#open the zip
print "GOT TO OPENING"
except zipfile.BadZipfile:
print "The error raised for bad ZIP files (old name: zipfile.error)."
except zipfile.LargeZipFile:
print "The error raised when a ZIP file would require ZIP64 functionality but that has not been enabled."
rules = ((check_tar, open_tar),
(check_zip, open_zip)
)
def checkall(file):
for checks, extracts in rules:
if checks(file):
return extracts(file)
def main():
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
parser.add_option("-f", "--file", dest="filename",
help="read data from FILENAME")
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("incorrect number of arguments")
file = options.filename
checkall(file)
if __name__ == '__main__':
main()
Your problem is probably the if len(args) != 1:. That is looking for an additional argument (i.e. not an option). If you remove that check and look at your options dictionary you should see {'filename': 'blah'}.
Your input filename isn't an option to the program, it's an argument:
def main():
usage = "Usage: %prog [options] FILE"
description = "Read data from FILE."
parser = OptionParser(usage, description=description)
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("incorrect number of arguments")
file = args[0]
checkall(file)
You can usually tell the difference because options generally have sensible defaults while arguments don't.
After parsing the options out of the argument list, you check that you were passed an argument. This is independent of the argument to -f. It sounds like you're just not passing this argument. Since you also don't actually use this argument, you should probably just remove the check on len(args).
You should set the 'action' attribute in the 'add_option()' method to 'store', this tells the optparse object to store the argument immediately following the option flag, though this is the default behavior. The value following the flag will then be stored in 'options.filename' and not in args. I also think that the
if len(args) != 1:
is also an issue, you will get the same message if len(args) is greater than or less than 1.