This is probably a silly question, but I have a python script that current takes in a bunch of arguments using argparser and I would like to load this script as a module in another python script, which is fine. But I am not sure how to call the module as no function is defined; can I still call it the same way I do if I was just invoking it from cmd?
Here is the child script:
import argparse as ap
from subprocess import Popen, PIPE
parser = ap.ArgumentParser(
description='Gathers parameters.')
parser.add_argument('-f', metavar='--file', type=ap.FileType('r'), action='store', dest='file',
required=True, help='Path to json parameter file')
parser.add_argument('-t', metavar='--type', type=str, action='store', dest='type',
required=True, help='Type of parameter file.')
parser.add_argument('-g', metavar='--group', type=str, action='store', dest='group',
required=False, help='Group to apply parameters to')
# Gather the provided arguments as an array.
args = parser.parse_args()
... Do stuff in the script
and here is the parent script that I want to invoke the child script from; it also uses arg parser and does some other logic
from configuration import parameterscript as paramscript
# Can I do something like this?
paramscript('parameters/test.params.json', test)
Inside the configuration directory, I also created an init.py file that is empty.
The first argument to parse_args is a list of arguments. By default it's None which means use sys.argv. So you can arrange your script like this:
import argparse as ap
def main(raw_args=None):
parser = ap.ArgumentParser(
description='Gathers parameters.')
parser.add_argument('-f', metavar='--file', type=ap.FileType('r'), action='store', dest='file',
required=True, help='Path to json parameter file')
parser.add_argument('-t', metavar='--type', type=str, action='store', dest='type',
required=True, help='Type of parameter file.')
parser.add_argument('-g', metavar='--group', type=str, action='store', dest='group',
required=False, help='Group to apply parameters to')
# Gather the provided arguments as an array.
args = parser.parse_args(raw_args)
print(vars(args))
# Run with command line arguments precisely when called directly
# (rather than when imported)
if __name__ == '__main__':
main()
And then elsewhere:
from first_module import main
main(['-f', '/etc/hosts', '-t', 'json'])
Output:
{'group': None, 'file': <_io.TextIOWrapper name='/etc/hosts' mode='r' encoding='UTF-8'>, 'type': 'json'}
There may be a simpler and more pythonic way to do this, but here is one possibility using the subprocess module:
Example:
child_script.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-n", "--name", help="your name")
args = parser.parse_args()
print("hello there {}").format(args.name)
Then another Python script can call that script like so:
calling_script.py:
import subprocess
# using Popen may suit better here depending on how you want to deal
# with the output of the child_script.
subprocess.call(["python", "child_script.py", "-n", "Donny"])
Executing the above script would give the following output:
"hello there Donny"
One of the option is to call it as subprocess call like below:
import subprocess
childproc = subprocess.Popen('python childscript.py -file yourjsonfile')
op, oe = childproc.communicate()
print op
Related
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument('p', 'projectType', type=str, help = 'c or c++ project type', choices=['c', 'c++'])
parser.add_argument('i', 'inputfile', type=pathlib.Path, help = 'the input file path')
parser.add_argument('o',"outputfile",type=pathlib.Path, help= 'the output file path')
parser.add_argument
args = parser.parse_args()
when i run this code on command prompt, and enter the inputfile first for example.. it gives me an error. does Argparse have an option like getopt (where i call something with a letter before inputting it so no mix up ex, '-i ...input...'). Here this option is just for optional arguments.
Is there a way for positional arguments to do that?
As per the argparse documentation you would define it as an "optional" argument but with the required flag set to true, e.g.:
parser.add_argument('-i', '--inputfile', required=True, type=pathlib.Path, help='the input file path')
I am trying to run one python script (Main_Script) which is supposed to get argparse flag and this script at the same time calls another script(Sub_Script) which is also supposed to get the flag to input. And when I call Main_Script I get an error which says that I can't use the flag because it is not defined in the script but it is actually defined. The error notification makes me use the flag from subscript instead.
MAIN_SCRIPT
parser = argparse.ArgumentParser(add_help=True)
parser.add_argument('-p', '--print_positive_results', action='store_true')
args = parser.parse_args()
PRINT_POSITIVE = args.print_positive_results
#I then use rhi global variable PRINT_POSITIVE
SUB_SCRIPT
import argparse
parser = argparse.ArgumentParser(add_help=True)
parser.add_argument('-d', '--debug', action='store_true')
args = parser.parse_args()
And when I call python MAIN_SCRIPT.py -p I get this
usage: test_grammar.py [-h] [-d]
test_grammar.py: error: unrecognized arguments: -p
DEBUG = False
if (args.debug ):
DEBUG = True
Seems like the command line args from the main script are passed through to the sub script.
You could try to (and probably should) wrap the argparse stuff into:
if __name__ == '__main__':
<argparse stuff>
With this the code is only called when the script is called from the command line. The real code could be outsourced into a function. This way you can use the script from command line with argparse and only import the function from the script if you call it from another script:
Main script:
import argparse
import subscript
if __name__ == '__main__':
parser = argparse.ArgumentParser(add_help=True)
parser.add_argument('-p', '--print_positive_results', action='store_true')
args = parser.parse_args()
...
subscript.your_function(<whatever your args are>)
...
Sub script:
import argparse
def your_function(<your args>):
<your code>
if __name__ == '__main__':
parser = argparse.ArgumentParser(add_help=True)
parser.add_argument('-d', '--debug', action='store_true')
args = parser.parse_args()
your_function(<whatever your args are>)
...
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
I am using Python argparse to take in parameters through the CLI. I have tried using the following but when I don't give any one of the arguments, it gives the output as None. I want then default ones to be the ones provided in const=. Please take a look.
parser = argparse.ArgumentParser()
parser.add_argument('--input', nargs='?', const='testInput')
parser.add_argument('--target', nargs='?', const='testTarget')
parser.add_argument('--msg', nargs='?', const='helloFromTheOtherSide')
args = parser.parse_args()
print args.input
If I don't give input, it prints it as None as I said. I want it to print TestInput instead..
Use the default argument:
parser = argparse.ArgumentParser()
parser.add_argument('--input', nargs='?', default='testInput')
parser.add_argument('--target', nargs='?', default='testTarget')
parser.add_argument('--msg', nargs='?', default='helloFromTheOtherSide')
args = parser.parse_args()
print args.input
With
parser.add_argument('--input', nargs='?', default='testInput', const='aConst')
you have a 3 way choice
prog # input='testInput'
prog --input # input='aConst'
prog --input myfile # input='myfile'
If you don't need that aConst option, omit the nargs='?'. Since it is a flagged argument it is already optional. It doesn't need the `?'.
parser.add_argument('--input', default='testInput')
write a script that takes two optional boolean arguments,"--verbose‚" and ‚"--live", and two required string arguments, "base"and "pattern". Please set up the command line processing using argparse.
This is the code I have so far for the question, I know I am getting close but something is not quite right. Any help is much appreciated.Thanks for all the quick useful feedback.
def main():
import argparse
parser = argparse.ArgumentParser(description='')
parser.add_argument('base', type=str)
parser.add_arguemnt('--verbose', action='store_true')
parser.add_argument('pattern', type=str)
parser.add_arguemnt('--live', action='store_true')
args = parser.parse_args()
print(args.base(args.pattern))
The string arguments are not required by default, so you need to state that. Also the print statement that uses the arguments is incorrect.
#!/usr/bin/python
import argparse
if __name__=="__main__":
parser = argparse.ArgumentParser(description='eg $python myargs.py --base arg1 --pattern arg2 [--verbose] [--live]')
parser.add_argument('--base', required=True, type=str)
parser.add_argument('--pattern', required=True, type=str)
parser.add_argument('--verbose', action='store_true')
parser.add_argument('--live', action='store_true')
args = parser.parse_args()
print "args.base=" + str(args.base)
print "args.pattern=" + str(args.pattern)
print "args.verbose=" + str(args.verbose)
print "args.live=" + str(args.live)
the #!/usr/bin/python at the top enables the script to be called directly, though python must be located there (to confirm, type $which python), and you must set the file to have execute permission ($chmod +x myargs.py)