命令行示例:
基本用法
$ python [file].py hello Kyle Hello, Kyle! $ python [file].py goodbye Kyle Goodbye, Kyle!
W/选项用法(标志)
$ python [file].py hello --greeting=Wazzup Kyle Whazzup, Kyle! $ python [file].py goodbye --greeting=Later Kyle Later, Kyle! $ python [file].py hello --caps Kyle HELLO, KYLE! $ python [file].py hello --greeting=Wazzup --caps Kyle WAZZUP, KYLE!
Argarse:标准库
def greet(args): output = '{0}, {1}!'.format(args.greeting, args.name) if args.caps: output = output.upper() print(output) parser = argparse.ArgumentParser() parser.add_argument('--version', action='version', version='1.0.0') subparsers = parser.add_subparsers() hello_parser = subparsers.add_parser('hello') hello_parser.add_argument('name', help='name of the person to greet') hello_parser.add_argument('--greeting', default='Hello', help='word to use for the greeting') hello_parser.add_argument('--caps', action='store_true', help='uppercase the output') hello_parser.set_defaults(func=greet) goodbye_parser = subparsers.add_parser('goodbye') goodbye_parser.add_argument('name', help='name of the person to greet') goodbye_parser.add_argument('--greeting', default='Hello', help='word to use for the greeting') goodbye_parser.add_argument('--caps', action='store_true', help='uppercase the output') goodbye_parser.set_defaults(func=greet) if __name__ == '__main__': args = parser.parse_args() args.func(args)
Docopt
"""usage: greet [--help][ ...] options: -h --help Show this screen. --version Show the version. commands: hello Say hello goodbye Say goodbye """ from docopt import docopt from schema import Schema, SchemaError, Optional HELLO = """usage: basic.py hello [options] [ ] -h --help Show this screen. --caps Uppercase the output. --greeting= Greeting to use [default: Hello]. """ GOODBYE = """usage: basic.py goodbye [options] [ ] -h --help Show this screen. --caps Uppercase the output. --greeting= Greeting to use [default: Goodbye]. """ def greet(args): output = '{0}, {1}!'.format(args['--greeting'], args[' ']) if args['--caps']: output = output.upper() print(output) if __name__ == '__main__': arguments = docopt(__doc__, options_first=True, version='1.0.0') schema = Schema({ Optional('hello'): bool, Optional('goodbye'): bool, ' ': str, Optional('--caps'): bool, Optional('--help'): bool, Optional('--greeting'): str }) def validate(args): try: args = schema.validate(args) return args except SchemaError as e: exit(e) if arguments[' '] == 'hello': greet(validate(docopt(HELLO))) elif arguments[' '] == 'goodbye': greet(validate(docopt(GOODBYE))) else: exit("{0} is not a command. See 'options.py --help'.".format(arguments[' ']))
Click
import click CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) def greeter(**kwargs): output = '{0}, {1}!'.format(kwargs['greeting'], kwargs['name']) if kwargs['caps']: output = output.upper() print(output) @click.group(context_settings=CONTEXT_SETTINGS) @click.version_option(version='1.0.0') def greet(): pass @greet.command() @click.argument('name') @click.option('--greeting', default='Hello', help='word to use for the greeting') @click.option('--caps', is_flag=True, help='uppercase the output') def hello(**kwargs): greeter(**kwargs) @greet.command() @click.argument('name') @click.option('--greeting', default='Goodbye', help='word to use for the greeting') @click.option('--caps', is_flag=True, help='uppercase the output') def goodbye(**kwargs): greeter(**kwargs) if __name__ == '__main__': greet()
Invoke
from invoke import task def greet(name, greeting, caps): output = '{0}, {1}!'.format(greeting, name) if caps: output = output.upper() print(output) HELP = { 'name': 'name of the person to greet', 'greeting': 'word to use for the greeting', 'caps': 'uppercase the output' } def print_version(): print('1.0.0') exit(0) @task(help=HELP) def hello(name='', greeting='Hello', caps=False, version=False): """ Say hello. """ if version: print_version() greet(name, greeting, caps) @task(help=HELP) def goodbye(name='', greeting='Goodbye', caps=False, version=False): """ Say goodbye. """ if version: print_version() greet(name, greeting, caps)
错误处理一般有三种情况:
1、参数不足。
2、无效的选项/标志。
3、需要标志给一个值。
Argparse
$ python argparse/final.py hello usage: final.py hello [-h] [--greeting GREETING] [--caps] name final.py hello: error: the following arguments are required: name $ python argparse/final.py --badoption hello Kyle usage: final.py [-h] [--version] {hello,goodbye} ... final.py: error: unrecognized arguments: --badoption $ python argparse/final.py hello --caps=notanoption Kyle usage: final.py hello [-h] [--greeting GREETING] [--caps] name final.py hello: error: argument --caps: ignored explicit argument 'notanoption'
Docopt,需借助于scheme
... from schema import Schema, SchemaError, Optional ... schema = Schema({ Optional('hello'): bool, Optional('goodbye'): bool, '': str, Optional('--caps'): bool, Optional('--help'): bool, Optional('--greeting'): str }) def validate(args): try: args = schema.validate(args) return args except SchemaError as e: exit(e) if arguments[' '] == 'hello': greet(validate(docopt(HELLO))) elif arguments[' '] == 'goodbye': greet(validate(docopt(GOODBYE))) ... $ python docopt/validation.py hello None should be instance of $ python docopt/validation.py hello --greeting Kyle None should be instance of $ python docopt/validation.py hello --caps=notanoption Kyle --caps must not have an argument usage: basic.py hello [options] [ ]
Click
$ python click/final.py hello Usage: final.py hello [OPTIONS] NAME Error: Missing argument "name". $ python click/final.py hello --badoption Kyle Error: no such option: --badoption $ python click/final.py hello --caps=notanoption Kyle Error: --caps option does not take a value
打包
entry_point本质上是一个到代码单一函数的映射,系统PATH将给出一个命令。entry_point的形式是command = package.module:function
包装click命令
greeter/ ├── greet │ ├── __init__.py │ └── cli.py <-- the same as our final.py └── setup.py
entry_points={ 'console_scripts': [ 'greet=greet.cli:greet', # command=package.module:function ], },
当用户安装entry_point创建的包时,setuptools将创建以下可执行脚本(调用greet)并放置它在用户系统的PATH。
#!/usr/bin/python if __name__ == '__main__': import sys from greet.cli import greet sys.exit(greet())
包装Argparse命令
代码:
if __name__ == '__main__': args = parser.parse_args() args.func(args)
变成:
def greet(): args = parser.parse_args() args.func(args) if __name__ == '__main__': greet()
针对entry_point,现在我们可以使用click中定义的相同的模式了。
包装Docopt命令
代码:
if __name__ == '__main__': arguments = docopt(__doc__, options_first=True, version='1.0.0') if arguments[''] == 'hello': greet(docopt(HELLO)) elif arguments[' '] == 'goodbye': greet(docopt(GOODBYE)) else: exit("{0} is not a command. See 'options.py --help'.".format(arguments[' ']))
变成:
def greet(): arguments = docopt(__doc__, options_first=True, version='1.0.0') if arguments[''] == 'hello': greet(docopt(HELLO)) elif arguments[' '] == 'goodbye': greet(docopt(GOODBYE)) else: exit("{0} is not a command. See 'options.py --help'.".format(arguments[' '])) if __name__ == '__main__': greet()