Passing command line arguments to Python function in script - python

I have a function which requires command line arguments (with optparse), which looks something like this:
def foo():
parser = optparse.OptionParser()
parser.add_option("-i", dest="input")
parser.add_option("-o", dest="output")
(options, args) = parser.parse_args()
do_something(options.input, options.output)
return
I need to call this function from another Python script.
Does anyone know how to pass arguments to this without making use of os.system('foo -i input_path -o output_path')?

Is it possible to change your structure to incorporate function arguments? If you are calling it from another script it would make it easier.
def foo(input, output):
parser = optparse.OptionParser()
parser.add_option("-i", dest="input")
parser.add_option("-o", dest="output")
(options, args) = parser.parse_args()
if options.input:
input=options.input
if options.output:
output=options.output
do_something(input, output)
return
Otherwise you can try subprocess when calling from the other script, as that allows you to use args

Related

python Argumentparser. executable file and source-code file as arguments

I can't figure out how to pass arguments from the command line properly. I want to pass an executable program and a source code file as arguments. It seems to be working well until I try to open the source code file. What am I doing wrong?
Command line:
$ my_script.py my_executable source_code.fe
Code:
import sys, argparse
def main():
parser = argparse.ArgumentParser(description='Description of program')
parser.add_argument('exe', type=argparse.FileType('r'))
parser.add_argument('src_file', type=argparse.FileType('r'))
#args = vars(parser.parse_args())
args = parser.parse_args()
infile = open(args.src_file)
#child = subprocess.run( [exe], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=infile)
if __name__ == "__main__":
FileType essentially produces a wrapper around open. The attribute in the value returned by parse_args is a file-like object already.
parser = argparse.ArgumentParser(description='Description of program')
parser.add_argument('exe', type=argparse.FileType('r'))
parser.add_argument('src_file', type=argparse.FileType('r'))
args = parser.parse_args()
infile = args.src_file
At its simplest, you could define FileType yourself as
def FileType(*args, **kwargs):
def _(fname):
return open(fname, *args, **kwargs)
return _
The real definition handles - as an alias for standard input or standard output as appropriate for the given mode, as well as better error handling.

Use argparse to send arguments to function within Python script

I am in the bit of a weird situation where I need a Python function to run from within a script, with the script then called from my main code.
I wanted to use the subprocess module, and know how to use it to pass arguments to a pure script, but the thing is, I need to pass the arguments to the nested Python function within, most of which are optional and have default values.
I thought arparse would help me do this somehow.
Here is an example of what I am trying:
## Some Argparse, which will hopefully help
import argparse
parser = argparse.ArgumentParser()
## All arguments, with only "follow" being required
parser.add_argument('file_name', help='Name of resulting csv file')
parser.add_argument('sub_name', help='Sub-name of resulting csv file')
parser.add_argument('follow', help='Account(s) to follow', required=True)
parser.add_argument('locations', help='Locations')
parser.add_argument('languages', help='Languages')
parser.add_argument('time_limit', help='How long to keep stream open')
args = parser.parse_args()
## Actual Function
def twitter_stream_listener(file_name=None,
sub_name='stream_',
auth = api.auth,
filter_track=None,
follow=None,
locations=None,
languages=None,
time_limit=20):
... function code ...
... more function code ...
...
...
## End of script
If you are passing arguments to functions all you need to do is feed them into the function when you're executing them:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-o", "--output_file_name", help="Name of resulting csv file")
parser.add_argument("-s", "--sub_name", default="stream_", help="Sub-name of resulting csv file")
parser.add_argument("-f", "--follow", help="Account(s) to follow", required=True)
parser.add_argument("-loc", "--locations", default=None, help="Locations")
parser.add_argument("-lan", "--languages", default=None, help="Languages")
parser.add_argument("-t", "--time_limit", default=20, help="How long to keep stream open")
options = parser.parse_args()
# then just pass in the arguments when you run the function
twitter_stream_listener(file_name=options.output_file_name,
sub_name=options.sub_name,
auth=api.auth,
filter_track=None,
follow=options.follow,
locations=options.locations,
languages=options.languages,
time_limit=options.time_limit)
# or, pass the arguments into the functions when defining your function
def twitter_stream_listener_with_args(file_name=options.output_file_name,
sub_name=options.sub_name,
auth=api.auth,
filter_track=None,
follow=options.follow,
locations=options.locations,
languages=options.languages,
time_limit=options.time_limit):
# does something
pass
# then run with default parameters
twitter_stream_listener_with_args()
You can specify defaults in the argparse section (if that is what you are trying to achieve):
#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--argument', default = 'something', type = str, help = 'not helpful')
parser.add_argument('--arg2', default = None, type = str, help = 'not helpful')
args = parser.parse_args()
def foo(arg , arg2 ):
print(arg)
if not arg2 is None:
print(arg2)
foo(args.argument, args.arg2)
Then calling:
$ ./test.py
something
$ ./test.py --argument='somethingelse'
somethingelse
$ ./test.py --arg2=123
something
123
$ ./test.py --arg2='ipsum' --argument='lorem'
lorem
ipsum
Is this helpful?
You can do it like that:
import argparse
## Actual Function
def twitter_stream_listener(file_name=None,
sub_name='stream_',
auth=api.auth,
filter_track=None,
follow=None,
locations=None,
languages=None,
time_limit=20):
# Your content here
if __name__ == '__main__':
parser = argparse.ArgumentParser()
## All arguments, with only "follow" being required
parser.add_argument('follow', help='Account(s) to follow')
parser.add_argument('--file_name', help='Name of resulting csv file')
parser.add_argument('--sub_name', help='Sub-name of resulting csv file')
parser.add_argument('--locations', help='Locations')
parser.add_argument('--languages', help='Languages')
parser.add_argument('--time_limit', help='How long to keep stream open')
args = parser.parse_args()
twitter_stream_listener(file_name=args.file_name, sub_name=args.sub_name, follow=args.follow,
locations=args.locations, languages=args.languages, time_limit=args.time_limit)
follow will be the only required argument and the rest optional. Optional ones have to be provided with -- at the beginning. You can easily use the module with subprocess if you need it.
Example call using command line:
python -m your_module_name follow_val --file_name sth1 --locations sth2

Creating artificially parsed arguments

My program "program.py" has the form:
if __name__=='__main__':
args = parse_args()
main_function(args)
However, if I import program.py as a module and run program.main_function, how can I pass the parsed arguments structure as an argument to the main_function?
Here is the definition of the parse_args()
def parse_args():
parser=argparse.ArgumentParser()
parser.add_argument(...)
args=parser.parse_args()
return args
If we are talking about argparse.parse_args from the standard library, just pass the list of arguments explicitly.
For example, if you call your program from the command line with these arguments:
program --verbose --mode=3 file1 file2
the shell splits the command line into five words, the program name and its four arguments. These are stored in sys.argv.
To achieve the same effect directly from Python:
args = parse_args(['--verbose', '--mode=3', 'file1' , 'file2'])
main_function(args)
UPDATE - parse_args modification:
def parse_args(arglist=None):
parser=argparse.ArgumentParser()
parser.add_argument(...)
args=parser.parse_args(arglist)
return args

merge options from two Python functions

I am writing a Python wrapper script for another python function which takes command line options using optparse, say -p and -i. In my wrapper function I'd like to add some other command line options that are not defined in the external function, e.g. -x. I am looking for a way to combine the the options defined in the external function with the ones I define in the wrapper. The external scripts has a function like this:
def extparser():
from optparse import OptionParser
parser = OptionParser(
prog="external-prog",
usage="%prog [options]")
parser.add_option(
"-p", "--parameter", type="int", default=1,
help="algo parameter")
parser.add_option(
"-i", "--iterations", type="int",
help="number of iterations")
(opts, args) = parser.parse_args()
return opts
I can't change the code in the external function. In my wrapper script I have something like :
#!/usr/bin/env python
from extprog import extparser
def newparser():
from optparse import OptionParser
parser = OptionParser(
prog="newprog",
usage="%prog [options]")
parser.add_option(
"-x", "--extraparam", type="int",
help="another parameter")
return parser.parse_args()
if __name__=="__main__":
extparser()
newparser()
Now, of course this doesn't work as expected :
[myhost]>./sotest.py -x 1 -p 2 -i 3
Usage: external-prog [options] <action> <name>
external-prog: error: no such option: -x
Is there a way to ignore the error from the external program? The real list of options in the external program is pretty long and I want to avoid copying it into the wrapper script.
There is no way to avoid getting that error while the external scripts optparse code is being called. What you can do is use the subprocess module to control which variables you pass to the external script by invoking it manually.
E.g:
subprocess.call(["external-prog", "-p", "some p value", "-i", "10"])

Python: Can optparse have the ACTION attribute to act both like STORE and STORE_TRUE?

I am using optparse to get command line input.
Lets say that I am running a script demo.py and it creates some output. But unless I specify the command line input, the output is not written to a file.
I am trying to do the following:
python demo.py in command line should run the script, but not write the output anywhere.
python demo.py -o in command line should write the output to my default file name output.txt.
python demo.py -o demooutput.txt in command line should write the output to file demooutput.txt.
PS: I would not prefer to switch to argparse from optparse.
You can use optparse-callbacks to achieve this.
Here is how it wiill work for your use case.
parser.add_option("-o", action="callback", dest="output", callback=my_callback)
def my_callback(option, opt, value, parser):
if len(parser.rargs) > 0:
next_arg = parser.rargs[0]
if not next_arg.startswith("-"):
# Next argument is not another option
del parser.rargs[0]
setattr(parser.values, option.dest, next_arg)
return
# If not processed, set the default value
setattr(parser.values, option.dest, "output.txt")
I don't think there is unfortunately - the only way I can think of is hacking around the problem by adding your own logic statements. The following code should do the trick.
import re, sys
import optparse from OptionParser
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
if '-f' in argv:
a = argv.index('-f')
if (a != len(argv)-1) and re.search('[.]txt', argv[a+1]):
parser.add_option("-f", "--foo", dest="foo")
else:
parser.add_option("-f", dest="foo", action="store_true")
This doesn't answer the direct question, 'how to define an Action...', but it handles the inputs in a simple way.
Set '-o' to be 'store_true'. If True check the 'args' variable for a file name.
(options, args) = parser.parse_args()
if options.o:
if args:
dest = args[0]
else:
dest = 'output.txt'
else:
dest = ''
(In argparse the equivalent would be to define a positional argument with nargs='?'.)
If these are the only arguments, you could also get by with checking for the filename without requiring the `-o'.
Another possibility - 'store_const', with the positional 'filename' having priority:
parser = optparse.OptionParser()
parser.add_option('-o',dest='dest',action='store_const', const='output.txt', default='')
(options, args) = parser.parse_args()
if args:
options.dest = args[0]
print options

Categories

Resources