Command line argument to run my own script - python

I have written a code function.py in python which has input file path and a output file path and some flags . currently I have hardcoded everything.I want to use command line arguments to provide these inputs so that anyone can run my script by providing input to cmd.how can I do it in python?
In CMD
function.py "input file path" "output file path"

A very rudimentary example would be:
import sys
input_file_path = sys.argv[1]
output_file_path = sys.argv[2]
Note that sys.argv[0] would be your filename. You should also do the relevant checks to make sure there are the correct number of arguments, whether they are valid, etc.

As an alternative to sys.argv, I prefer argparse.
As an example:
# Import the argparse module
import argparse
# Define a function to use argparse to parse your command-line arguments
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument(
"-i",
"--input-file",
dest="input_file",
help="File to use as input",
type=str
)
parser.add_argument(
"-o",
"--output-file",
dest="output_file",
help="File to output to",
type=str
)
return parser.parse_args()
# If calling this module from the command line, this `if` statement will evaluate to True
if __name__ == "__main__":
# Parse your command-line arguments
args = parse_args()
# Get the parsed value of the "-i" argument:
infile = args.input_file
# Get the parsed value of the "-o" argument:
outfile = args.output_file

Related

Python3 argparse: When passing string as arg run funcA, if dashed arg run another func

Here's what I'm trying to accomplish:
When passing a string as the arg, call a write_text() function
python3 app.py write this text to file
When passing a dashed arg, call another function, in this case read_text()
python3 app.py -r
When passing no args print help
python3 app.py
Here's what I have so far:
parser = argparse.ArgumentParser()
parser.add_argument('text', help="write text to file")
parser.add_argument('-r', '--read', help="read text from file")
args = parser.parse_args()
...
def main():
if args.read:
read_text()
elif args.text:
write_text(args.text)
else:
parser.print_help()
The problem is that when I call just -r it complains that it's missing a command for text, because text is not an optional argument.
I've tried creating subcommands and making all the args subcommands but then the text argument needs to be explicitly called like python3 app.py text.
I may be thinking too hard on this and overlooking a simple solution. I had this working perfectly just parsing sys.argv, but it wasn't pretty. And the built in help function is useful as well.
Thanks in advance!
Edit:
Here's what I have now that's working
parser = argparse.ArgumentParser()
parser.add_argument('text', nargs='*', help="write text to file")
parser.add_argument('-r', '--read', action='store_true', help="read text from file")
args = parser.parse_args()
...
def main():
if args.read:
read_text()
elif args.text:
text = " ".join(args.text)
write_text(text)
else:
parser.print_help()
Still thinking there may be a cleaner way to do this...
This might help :
parser.add_argument('text', nargs='?', help="write text to file")
more info : https://docs.python.org/3/library/argparse.html#nargs
Note that you should use action='store_true' for the read argument if you want to use args.read as a boolean later.
parser.add_argument('-r', '--read', action='store_true', help="read text from file")

How do I add sys.argv to a function opening a text file in Python

I need to use sys.argv to check for an argument from the command line, which would be the filename in my case. My code is as follows. I'm not allowed to import argparse, only allowed to use sys. I know I'm doing something wrong here. Appreciate any help.
def get_inputfile_object( ):
'''
Check the command line for an argument. If one was there, use it as the
filename. Otherwise, use DEFAULT_INPUT_FILENAME. Open the file.
If file is successfully opened:
print MSG_OPENING_FILE
Return: a file object for that file
If the file cannot be opened:
print MSG_ERROR_OPENNING_FILE
Return: True
'''
if sys.argv > 1:
pass
else:
input_filename = DEFAULT_INPUT_FILENAME
input_filename = DEFAULT_INPUT_FILENAME
if os.path.isfile(input_filename) and os.access(input_filename,os.R_OK):
#Prints the opening file message, and the name of the file
print (MSG_OPENING_FILE,input_filename)
return open(input_filename,'r')
else:
print (MSG_ERROR_OPENING_FILE)
return True
sys.argv is a list of arguments.
You need to check the length of the list:
if len(sys.argv) > 1:
You should check out argparse.
The argparse module also automatically generates help and usage
messages and issues errors when users give the program invalid
arguments.
Haven't tested it, but you can try something similar to this:
import argparse
# setup the parser
parser = argparse.ArgumentParser(description='Describe script')
# add positional argument
parser.add_argument('filename', type=str, help='filename description')
# parse the args
args = parser.parse_args()
print(args.filename)

Having options in argparse with a dash

I want to have some options in argparse module such as --pm-export however when I try to use it like args.pm-export I get the error that there is not attribute pm. How can I get around this issue? Is it possible to have - in command line options?
As indicated in the argparse docs:
For optional argument actions, the value of dest is normally inferred from the option strings. ArgumentParser generates the value of dest by taking the first long option string and stripping away the initial -- string. Any internal - characters will be converted to _ characters to make sure the string is a valid attribute name
So you should be using args.pm_export.
Unfortunately, dash-to-underscore replacement doesn't work for positional arguments (not prefixed by --).
E.g:
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('logs-dir',
help='Directory with .log and .log.gz files')
parser.add_argument('results-csv', type=argparse.FileType('w'),
default=sys.stdout,
help='Output .csv filename')
args = parser.parse_args()
print args
# gives
# Namespace(logs-dir='./', results-csv=<open file 'lool.csv', mode 'w' at 0x9020650>)
So, you should use 1'st argument to add_argument() as attribute name and metavar kwarg to set how it should look in help:
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('logs_dir', metavar='logs-dir',
nargs=1,
help='Directory with .log and .log.gz files')
parser.add_argument('results_csv', metavar='results-csv',
nargs=1,
type=argparse.FileType('w'),
default=sys.stdout,
help='Output .csv filename')
args = parser.parse_args()
print args
# gives
# Namespace(logs_dir=['./'], results_csv=[<open file 'lool.csv', mode 'w' at 0xb71385f8>])
Dashes are converted to underscores:
import argparse
pa = argparse.ArgumentParser()
pa.add_argument('--foo-bar')
args = pa.parse_args(['--foo-bar', '24'])
print args # Namespace(foo_bar='24')
Concise and explicit but probably not always acceptable way would be to use vars():
#!/usr/bin/env python3
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('a-b')
args = vars(parser.parse_args())
print(args['a-b'])
getattr(args, 'positional-arg')
This is another OK workaround for positional arguments:
#!/usr/bin/env python3
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('a-b')
args = parser.parse_args(['123'])
assert getattr(args, 'a-b') == '123'
Tested on Python 3.8.2.
I guess the last option is to change shorten option -a to --a
import argparse
parser = argparse.ArgumentParser(description="Help")
parser.add_argument("--a", "--argument-option", metavar="", help="") # change here
args = parser.parse_args()
option = args.a # And here
print(option)

Take string argument from command line?

I need to take an optional argument when running my Python script:
python3 myprogram.py afile.json
or
python3 myprogram.py
This is what I've been trying:
filename = 0
parser = argparse.ArgumentParser(description='Create Configuration')
parser.add_argument('filename', type=str,
help='optional filename')
if filename is not 0:
json_data = open(filename).read()
else:
json_data = open('defaultFile.json').read()
I was hoping to have the filename stored in my variable called "filename" if it was provided. Obviously this isn't working. Any advice?
Please read the tutorial carefully. http://docs.python.org/howto/argparse.html
i believe you need to actually parse the arguments:
parser = argparse.ArgumentParser()
args = parser.parse_args()
then filename will be come available args.filename
Check sys.argv. It gives a list with the name of the script and any command line arguments.
Example script:
import sys
print sys.argv
Calling it:
> python script.py foobar baz
['script.py', 'foobar', 'baz']
If you are looking for the first parameter sys.argv[1] does the trick. More info here.
Try argparse's default parameter, its well documented.
import argparse
parser = argparse.ArgumentParser(description='Create Configuration')
parser.add_argument('--file-name', type=str, help='optional filename',
default="defaultFile.json")
args = parser.parse_args()
print(args.file_name)
Output:
$ python open.py --file-name option1
option1
$ python open.py
defaultFile.json
Alternative library:
click library for arg parsing.

Consistent way to redirect both stdin & stdout to files in python using optparse

I've got a dozen programs that can accept input via stdin or an option, and I'd like to implement the same features in a similar way for the output.
The optparse code looks like this:
parser.add_option('-f', '--file',
default='-',
help='Specifies the input file. The default is stdin.')
parser.add_option('-o', '--output',
default='-',
help='Specifies the output file. The default is stdout.')
The rest of the applicable code looks like this:
if opts.filename == '-':
infile = sys.stdin
else:
infile = open(opts.filename, "r")
if opts.output == '-':
outfile = sys.stdout
else:
outfile = open(opts.output, "w")
This code works fine and I like its simplicity - but I haven't been able to find a reference to anyone using a default value of '-' for output to indicate stdout. Is this a good consistent solution or am I overlooking something better or more expected?
For input files you could use fileinput module. It follows common convention for input files: if no files given or filename is '-' it reads stdin, otherwise it reads from files given at a command-line.
There is no need in -f and --file options. If your program always requires an input file then it is not an option.
-o and --output is used to specify the output file name in various programs.
optparse
#!/usr/bin/env python
import fileinput
import sys
from optparse import OptionParser
parser = OptionParser()
parser.add_option('-o', '--output',
help='Specifies the output file. The default is stdout.')
options, files = parser.parse_args()
if options.output and options.output != '-':
sys.stdout = open(options.output, 'w')
for line in fileinput.input(files):
process(line)
argparse
argparse module allows you to specify explicitly files as arguments:
#!/usr/bin/env python
import fileinput
import sys
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument('files', nargs='*', help='specify input files')
group = parser.add_mutually_exclusive_group()
group.add_argument('-o', '--output',
help='specify the output file. The default is stdout')
group.add_argument('-i', '--inplace', action='store_true',
help='modify files inplace')
args = parser.parse_args()
if args.output and args.output != '-':
sys.stdout = open(args.output, 'w')
for line in fileinput.input(args.files, inplace=args.inplace):
process(line)
Note: I've added --inplace option in the second example:
$ python util-argparse.py --help
usage: util-argparse.py [-h] [-o OUTPUT | -i] [files [files ...]]
positional arguments:
files specify input files
optional arguments:
-h, --help show this help message and exit
-o OUTPUT, --output OUTPUT
specify the output file. The default is stdout
-i, --inplace modify files inplace
If you can use argparse (i.e. Python 2.7+), it has built-in support for what you want: straight from argparse doc
The FileType factory creates objects that can be passed to the type argument of ArgumentParser.add_argument(). Arguments that have FileType objects as their type will open command-line arguments […] FileType objects understand the pseudo-argument '-' and automatically convert this into sys.stdin for readable FileType objects and sys.stdout for writable FileType objects.
So my advice is to simply use
import sys
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('file', type=argparse.FileType('r'),
help="Specifies the input file")
parser.add_argument('output', type=argparse.FileType('w'),
help="Specifies the output file")
args = parser.parse_args(sys.argv[1:])
# Here you can use your files
text = args.file.read()
args.output.write(text)
# … and so on
Then you can do
> python spam.py file output
To read from file and output to output, or
> echo "Ni!" | python spam.py - output
to read "Ni!" and output to output, or
> python spam.py file -
…
And it's good, since using - for the relevant stream is a convention that a lot of programs use. If you want to point it out, add it to the help strings.
parser.add_argument('file', type=argparse.FileType('r'),
help="Specifies the input file, '-' for standard input")
For reference, the usage message will be
> python spam.py -h
usage: [-h] file output
positional arguments:
file Specifies the input file, '-' for standard input
output Specifies the output file, '-' for standard output
optional arguments:
-h, --help show this help message and exit

Categories