If you want to create some command (CLI), you use argparse. Here are some tips on how to use this argparse comfortably and conveniently with as little effort as possible.
sys.argv
In some argparse usage introductions, I'm seriously passing sys.argv
. You do not need. Calling parse_args ()
with no arguments will do just fine.
import argparse
parser = argparse.ArgumentParser()
parser.parse_args() #This is OK
If you add -h
or --help
, argparse will automatically add the function to display the help message. On top of that, it is convenient to leave the behavior when you make a mistake in the usage to argparse.
You don't need to write this kind of code, for example, if you run it with no arguments.
import sys
#This code is unnecessary
if len(sys.argv) == 0:
parser.parse_args(["-h"])
I just wanted to tell you that it's unnecessary because there were so many good things about this article.
-[Template when creating a command line application with Python --Qiita](http://qiita.com/Alice1017/items/0464a38ab335ac3b9336#python%E3%81%A7%E3%82%B3%E3%83%9E% E3% 83% B3% E3% 83% 89% E3% 83% A9% E3% 82% A4% E3% 83% B3% E3% 82% A2% E3% 83% 97% E3% 83% AA% E3% 82% B1% E3% 83% BC% E3% 82% B7% E3% 83% A7% E3% 83% B3% E3% 82% 92% E4% BD% 9C% E3% 82% 8B% E3% 81% A8% E3% 81% 8D% E3% 81% AE% E9% 9B% 9B% E5% BD% A2)
Postscript:
It seems that the intention of this code was to give all long help instead of short usage message on error. It's a bit hacky, but you can write it like this (although some people may prefer the original code, which clearly shows what's going on):
parser.print_usage = parser.print_help
If you specify even one positional argument, the lack of arguments is automatically checked, so you do not need to do anything.
import argparse
parser = argparse.ArgumentParser("<command name>")
parser.add_argument("file") # positional argument
args = parser.parse_args()
$ python cmd.py
usage: <command name> [-h] file
<command name>: error: the following arguments are required: file
If everything was optional, add required = True
to what seems to be required (although there is talk of a positional argument if required).
import argparse
parser = argparse.ArgumentParser("<command name>")
parser.add_argument("--file", required=True)
args = parser.parse_args()
$ python cmd.py
usage: <command name> [-h] --file FILE
<command name>: error: the following arguments are required: file
Another possible behavior is when it is executed without specifying any arguments. It is to process by embedding the default value. This can be specified with default
.
For example, you may want to create a command that receives data from standard input if you don't specify a file.
If specified in a positional argument, use nargs ="? "
To make it optional
import sys
import argparse
parser = argparse.ArgumentParser("hai")
parser.add_argument("file", nargs="?", type=argparse.FileType("r"), default=sys.stdin)
args = parser.parse_args()
print(args.file.read())
This will work.
$ cat hello.txt | python echo.py
$ python echo.py hello.txt
For optional arguments, just specify default.
parser.add_argument("--file", type=argparse.FileType("r"), default=sys.stdin)
It is useful to remember the action received by the parser's add_argument. You don't have to remember everything, but it's easier to remember some actions.
For example, use store_true when you have flags like --with- <something>
or options that take no arguments like --debug
. default value will be False
parser.add_argument("--debug", action="store_true")
Conversely, use store_false if the flag is --without- <something>
, or if default is set to True and the option is set to False.
parser.add_argument("--execute", action="store_false") #default is dry-Situation like run
Note that if you want to provide both the with-foo
and without-foo
flags, you should specify the default values with set_defaults (). Otherwise, the default value will depend on the order in which you wrote it.
#default is debug=False
parser.add_argument("--without-debug", action="store_false", dest="debug")
parser.add_argument("--with-debug", action="store_true", dest="debug")
parser.set_defaults(debug=False)
If you want to take multiple values, specify append for action.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--target", action="append")
args = parser.parse_args()
print(args)
It works as follows.
$ python cmd.py --target x --target y --target z
Namespace(target=['x', 'y', 'z'])
If you want to limit the range of possible values, it is convenient to use choices. For example, the part that specifies the logging level should be written as follows.
import argparse
import logging
parser = argparse.ArgumentParser()
loglevels = list(logging._nameToLevel.keys()) # _It ’s a prefix, so it ’s not well-behaved.
parser.add_argument("--loglevel", choices=loglevels, default="INFO")
args = parser.parse_args()
logging.basicConfig(level=args.loglevel)
logger = logging.getLogger("log")
logger.debug("hmm..")
logger.info("hmm")
I feel that info is good for default.
$ python cmd.py
INFO:log:hmm
$ python cmd.py -h
usage: cmd.py [-h]
[--loglevel {WARN,INFO,NOTSET,DEBUG,CRITICAL,WARNING,ERROR}]
optional arguments:
-h, --help show this help message and exit
--loglevel {WARN,INFO,NOTSET,DEBUG,CRITICAL,WARNING,ERROR}
$ python cmd.py --loglevel=DEBUG
DEBUG:log:hmm..
INFO:log:hmm
It is more useful to look at the official document than to read this article because the explanation of the official document is useful in detail. See the official documentation.
If you want to create a subcommand, give up argparse early and use click.
After that, it is useful to remember one package that can be executed as a command from the function definition (I made it myself).
For example, it is as follows.
# greeting.py
from handofcats import as_command
@as_command
def greeting(message, is_surprised=False, name="foo"):
suffix = "!" if is_surprised else ""
print("{name}: {message}{suffix}".format(name=name, message=message, suffix=suffix))
$ pip install handofcats
$ python greeting.py -h
python greeting.py -h
usage: greeting.py [-h] [--is-surprised] [--name NAME] [-v] [-q] message
positional arguments:
message
optional arguments:
-h, --help show this help message and exit
--is-surprised
--name NAME
-v, --verbose (default option: increment logging level(default is
WARNING))
-q, --quiet (default option: decrement logging level(default is
WARNING))
$ python greeting.py
foo: hello
$ python greeting.py --is-surprised --name me hello
me: hello!
Recommended Posts