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.
Answer from BrenBarn on Stack OverflowI 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).
Videos
I have some across three ways I've seen argparse placed in applications. They go roughly like this...
First way:
def main(some_arguments):
do_something(some_arguments)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='This.')
yada yada
main(some_arguments) Second way:
def main():
parser = argparse.ArgumentParser(description='This.')
yada yada
if __name__ == '__main__':
main()And a third way:
def parse_args():
parser = argparse.ArgumentParser(description='This.')
yada yada
return something
def main():
args = parse_args()
if __name__ == '__main__':
main()Is there a preferred way to do it? Are they contingent on some factors that are not immediately apparent to me? Or are they all equivalent and just a matter of taste?
Personally, I think the first way makes the most sense, or a combination of the first and third.
Something like:
def main(some_args):
do_stuff...
def parse_arguments():
argument_parse_code
return arguments
if __name__ == '__main__':
arguments = parse_arguments()
main(*arguments)
My thinking: By defining main with args, you can then import that script elsewhere and call the main function with arguments from the calling script.
By definite the argument parsing in a separate script, you can test more easily, and write unit tests to verify functionality.
I think it's a matter of taste, style and designing your code "well".
While not giving a direct response, here's what I like to do - this works for simple utilities, but doesn't change that much for more complicated stuff:
-
usually you have a function/object that does all the work, or at least serves as an entry point to your app logic
-
having that in mind, let main() do two things: call a
configure()function that returns parsed args; calldo_stuff(arg1, arg2, arg3)using parsed args -
do_stuff()doesn't need to depend on some arbitraryargsobject - rather, it receives explicit arguments
Profits:
-
main()servers as a dispatcher, which makes it simple; you might have different logic depending on an argument, let main() dispatch it (there are cool options for complex stuff) -
configure()is where all your commandline options live -
do_stuff()is easy to test, easy to import into other projects which might not even have commandline arguments, perhaps you pull them from a DB or a config file?
Here's the way I do it with argparse (with multiple args):
parser = argparse.ArgumentParser(description='Description of your program')
parser.add_argument('-f','--foo', help='Description for foo argument', required=True)
parser.add_argument('-b','--bar', help='Description for bar argument', required=True)
args = vars(parser.parse_args())
args will be a dictionary containing the arguments:
if args['foo'] == 'Hello':
# code here
if args['bar'] == 'World':
# code here
In your case simply add only one argument.
Editor's note: The docs say this:
Note: Required options are generally considered bad form because users expect options to be optional, and thus they should be avoided when possible.
Use positional arguments instead, e.g. as shown in @mightypile's answer.
My understanding of the question is two-fold. First, the simplest possible argparse example. Of course, to be dead-simple, it's got to be a toy example, i.e. all overhead with little power, but it might get you started.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("a")
args = parser.parse_args()
if args.a == 'magic.name':
print('You nailed it!')
But this positional argument is now required. If you leave it out when invoking this program, you'll get an error about missing arguments. This leads me to the second part of the question. You seem to want a single optional argument without a named label (the --option labels). My suggestion would be to modify the code above as follows:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("a", nargs='?')
args = parser.parse_args()
if args.a is None:
print('I can tell that no argument was given and I can deal with that here.')
elif args.a == 'magic.name':
print('You nailed it!')
else:
print(args.a)
There may well be a more elegant solution, but this works and is minimalist.
Note: If you want a different default value instead of None, use the default parameter to .add_argument.