I have a foo.py using argparse to get command line parameters for the main() function.
""" foo.py """
import argparse
def main():
parser = argparse.ArgumentParser(description='test')
parser.add_argument('--all', '-a', action='store_true', help='all')
args = parser.parse_args()
if args.all:
pass
if __name__ == '__main__':
main()
And I have to test this main() function on another Python script bar.py. My question is how to pass parameters in bar.py. My current solution is changing the sys.argv. Looking for better solution.
""" bar.py """
import sys
import foo
if __name__ == '__main__':
sys.argv.append('-a')
foo.main()
You can modify main function to receive a list of args.
""" foo.py """
import argparse
def main(passed_args=None):
parser = argparse.ArgumentParser(description='test')
parser.add_argument('--all', '-a', action='store_true', help='all')
args = parser.parse_args(passed_args)
if args.all:
pass
if __name__ == '__main__':
main()
""" bar.py """
import sys
import foo
if __name__ == '__main__':
foo.main(["-a"])
Related
Trying to run my script using argparser, where the program does not run, unless correct argument is in place, however it does not seem to work;
AttributeError: 'Namespace' object has no attribute 'func'
import sys
import argparse
from develop import Autogit as gt
def main():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
# Create argument command
parser_update = subparsers.add_parser('--sync', help='Sync local and remote repos')
parser_update.set_defaults(func=gt.run)
# Adding arguments
parser.add_argument('--sync', type=str, required=True)
if len(sys.argv) <= 1:
sys.argv.append('--help')
options = parser.parse_args()
options.func() # <--- Causes the error
if __name__ == '__main__':
main()
Also when the --sync arg is given it ask for another, then when I add one more argument. SYNC, then it returns attribute error.
Edit
Trying to make the program run the develop.Autogit.run
Working..
Had to also add args as argument in the run funciton i am calling.
I think what you are trying to accomplish is setting a default, typically this is done with ArgumentParser.set_defaults(). You need to do this with the uninitialised function. See this example:
import sys
import argparse
def f(args):
print("In func")
print(args)
def main():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
# Create argument command
parser_update = subparsers.add_parser("sync", help="Sync local and remote repos")
parser_update.set_defaults(func=f) # <-- notice it's `f` not `f()`
options = parser.parse_args()
options.func(options)
if __name__ == "__main__":
main()
As an aside, you will have more problems with your snippet as you are defining the same parameter (--sync) in multiple places. When using subparsers it is customary to make these positional (no leading --) so they act as subcommands.
Here is a typical command line that I would use with subcommands:
import sys
import argparse
def f(args):
print("In func f")
print(args)
def g(args):
print("In func g")
print(args)
def main():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest="command")
parser_update = subparsers.add_parser("sync", help="Sync local and remote repos")
parser_update.set_defaults(func=f)
parser_delete = subparsers.add_parser("delete", help="Delete sub-command")
parser_delete.set_defaults(func=g)
options = parser.parse_args()
if options.command is not None:
options.func(options)
else:
parser.print_help()
parser.exit()
if __name__ == "__main__":
main()
I am experimenting with the argparse module and I am having trouble understanding how to pass arguments from the parser constructed in main() to a new function that will use the arguments. I have tried reading some books and documentation on this topic, but I only feel more confused. I have pasted my code below.
CODE:
import argparse
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--skip", "-s", help="Skip updates to configuration.",
action="store_true")
args = parser.parse_args()
def config_check(*pass args here from main*):
if args.skip:
print("Not making modifications!")
else:
print("Making modifications!")
if __name__ == "__main__":
main()
Just like how you would pass any other argument.
import argparse
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--skip", "-s", help="Skip updates to configuration.",
action="store_true")
args = parser.parse_args()
config_check(args)
def config_check(args):
if args.skip:
print("Not making modifications!")
else:
print("Making modifications!")
if __name__ == "__main__":
main()
The idea is to add a flag (--slack, or -s) when running the script, so that I don't have to comment out the rep.post_report_to_slack() method every time I don't want to use it. When I run:
$ python my_script.py --slack
I get the error:
my_script.py: error: unrecognized arguments: --slack
Here's the code:
def main():
gc = Google_Connection()
meetings = gc.meetings
rep = Report(meetings)
if args.slack:
rep.post_report_to_slack()
print('posted to slack')
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--slack', help='post to slack',
action='store_true')
args = parser.parse_args()
main()
Your code works, but it relies on args being available in the module namespace, which isn't great because, for one thing, it means you can't use your function without calling the script from the command line. A more flexible and conventional approach would be to write the function to accept whatever arguments it needs, and then pass everything you get from argparse to the function:
# imports should usually go at the top of the module
import argparse
def get_meeting_report(slack=False):
gc = Google_Connection()
meetings = gc.meetings
rep = Report(meetings)
if slack:
rep.post_report_to_slack()
print('posted to slack')
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--slack', help='post to slack',
action='store_true')
args = parser.parse_args()
args = vars(args)
get_meeting_report(**args)
Now you can also more easily use your function outside of argparse by calling it directly.
I have two python scripts with the following structure:
# Script1.py
from optparse import OptionParser
def main():
parser = OptionParser()
parser.add_option("-a", "--add-foobar", action="store_true", help="set foobar true",
dest="foobar", default=False)
options, args = parser.parse_args()
print options.foobar
if __name__ == "__main__":
main()
# Script2.py
from Script1 import main as script1Main
def main():
script1Main()
Is there a way to pass command line arguments from script 2 to script 1? Script 1 in this example is immutable, therefore this must be done only thorough optparse.
If you don't pass any arguments to parse_args, it just uses the value of sys.argv[1:], which is going to be whatever arguments were passed when you called Script2.py. The fact that Script2.py calls Script1.main doesn't change that.
Firstly, maybe use argparse instead. You can process all arguments in script 2, then pass the argument handle to script 1.
# Script1.py
def main(args):
print args
# Script2.py
import argparse
from Script1 import main as script1Main
def main():
parser = argparse.ArgumentParser(
parser.add_option("-a", "--add-foobar", action="store_true", help="set foobar true", default=False)
args = parser.parse_args()
script1Main(args)
if __name__ == "__main__":
main()
If I am using argparse and an if __name__ == '__main__' test in a script that I would also like to use as a module, should I import argparse under that test and then initialize it? None of the style guides I have found mention using argparse in scripts and many examples of argparse scripting do not use the 'if name' test or use it differently. Here is what I have been going with so far:
#! /usr/bin/env python
def main(name):
print('Hello, %s!' % name)
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description = 'Say hello')
parser.add_argument('name', help='your name, enter it')
args = parser.parse_args()
main(args.name)
Should I import argparse with my other modules at the top and configure it in the body of the script instead?
I would put the import at the top, but leave the code that uses it inside the if __name__ block:
import argparse
# other code. . .
def main(name):
print('Hello, %s!' % name)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description = 'Say hello')
parser.add_argument('name', help='your name, enter it')
args = parser.parse_args()
main(args.name)
Putting the imports at the top clarifies what modules your module uses. Importing argpase even when you don't use it will have negligible performance impact.
It's fine to put the import argparse within the if __name__ == '__main__' block if argparse is only referred to within that block. Obviously the code within that block won't run if your module is imported by another module, so that module would have to provide its own argument for main (possibly using its own instance of ArgumentParser).