• CLI makers


    Argparse

    https://www.geeksforgeeks.org/argparse-vs-docopt-vs-click-comparing-python-command-line-parsing-libraries/

    python内置库。

    使用代码形式定义CLI.

    Argparse is a user-friendly command line interface. The argparse module parses the command-line arguments and options/flags.

    # argparse_example.py
    
    import argparse
    
    if __name__=='__main__':
        
        #Initialize
        parser=argparse.ArgumentParser(description="Simple calculator")
        
        #Adding optional parameters
        parser.add_argument('-n1',
                            '--num1',
                            help="Number 1",
                            type=float)
    
        parser.add_argument('-n2',
                            '--num2',
                            help="Number 2",
                            type=float)
    
        parser.add_argument('-op',
                            '--operation',
                            help="operator",
                            default="*")
        
        #Parsing the argument
        args=parser.parse_args()
        print(args)
    
        #Initialize result to None
        result =None
    
        #Simple calculator operations
        if args.operation == '+':
            result=args.num1+args.num2
    
        if args.operation == '-':
            result=args.num1-args.num2
    
        if args.operation == '/':
            result=args.num1/args.num2
    
        if args.operation == '*':
            result=args.num1*args.num2
    
        if args.operation == 'pow':
            result=pow(args.num1,args.num2)
        
        #Print the result
        print("Result = " ,result)

    CLICK

    https://www.geeksforgeeks.org/argparse-vs-docopt-vs-click-comparing-python-command-line-parsing-libraries/

    argparse升级版本,flask团队实现。

    使用装饰器把参数绑定到main函数的参数上。

    除了argparse外,被使用的最广泛的一个库,功能丰富。

    https://click.palletsprojects.com/en/8.1.x/

    Click is a Command Line Interface Creation Kit, it helps in arbitrary nesting of commands, automatic help page generation, supports lazy loading of subcommands at runtime. It aims to make the process of writing command-line tools quick and fun while also preventing any frustration caused by the inability to implement an intended CLI API. It comes with useful common helpers (getting terminal dimensions, ANSI colors, fetching direct keyboard input, screen clearing, finding config paths, launching apps and editors, etc.)

    # click_example.py
    
    import click
    
    # initialize result to 0
    result=0
    
    @click.command()
    @click.option('--num1',
                default=1,
                help='Enter a float value',
                type=float)
    
    @click.option('--num2',
                default=1,
                help='Enter a float value',
                type=float)
    
    @click.option('--op',
                default='+',
                help='Enter the operator')
    
    # Calculator function
    def calculator(num1,num2,op):
        if op=='+':
            result=num1+num2
        if op=='*':
            result=num1*num2
        if op=='-':
            result=num1-num2
        if op=='/':
            result=num1/num2
    
        # print the result
        click.echo("Result is %f" %result)
    
    if __name__ =='__main__':
        calculator()

    Typer

    https://typer.tiangolo.com/

    click的升级版本, 依赖click实现。

    FASTAPI团队实现。

    依赖注入方式,对每个参数做注解

    相对click,更加implict。

    Typer is a library for building CLI applications that users will love using and developers will love creating. Based on Python 3.6+ type hints.

    The key features are:

    • Intuitive to write: Great editor support. Completion everywhere. Less time debugging. Designed to be easy to use and learn. Less time reading docs.
    • Easy to use: It's easy to use for the final users. Automatic help, and automatic completion for all shells.
    • Short: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
    • Start simple: The simplest example adds only 2 lines of code to your app: 1 import, 1 function call.
    • Grow large: Grow in complexity as much as you want, create arbitrarily complex trees of commands and groups of subcommands, with options and arguments.
    import typer
    
    app = typer.Typer()
    
    
    @app.command()
    def hello(name: str):
        print(f"Hello {name}")
    
    
    @app.command()
    def goodbye(name: str, formal: bool = False):
        if formal:
            print(f"Goodbye Ms. {name}. Have a good day.")
        else:
            print(f"Bye {name}!")
    
    
    if __name__ == "__main__":
        app()

    Docopt

    https://www.geeksforgeeks.org/argparse-vs-docopt-vs-click-comparing-python-command-line-parsing-libraries/

    使用文档的风格定义CLI

    别具一格。

    https://github.com/docopt/docopt

    http://docopt.org/

    Docopt creates command line interface for the command line app, it automatically generates a parser for it. The main idea of docopt is to describe the interface literally with text, as in docstring.

    #docopt_example.py
    
    #usage pattern
    usage='''
    
    Usage:
    docopt_example.py command --option <argument>
    docopt_example.py <argument> <repeating-argument>
    docopt_example.py --version
    
    Options:
    -h, --help     Display help
    -o, --option Display options
    -l, --all     List all
    -q, --quit     exit
    --version     Version 3.6.1
        
    '''
    
    #Initialization
    from docopt import docopt
    
    args=docopt(usage)
    print(args)

    简单例

    https://riptutorial.com/python/example/4501/basic-example-with-docopt

    """
    Usage:
        script_name.py [-a] [-b] <path>
    
    Options:
        -a            Print all the things.
        -b            Get more bees into the path.
    """
    from docopt import docopt
    
    
    if __name__ == "__main__":
        args = docopt(__doc__)
        import pprint; pprint.pprint(args)

    解析结果存储在args中

    $ python script_name.py
    Usage:
        script_name.py [-a] [-b] <path>
    $ python script_name.py something
    {'-a': False,
     '-b': False,
     '<path>': 'something'}
    $ python script_name.py something -a
    {'-a': True,
     '-b': False,
     '<path>': 'something'}
    $ python script_name.py -b something -a
    {'-a': True,
     '-b': True,
     '<path>': 'something'}

    子命令例

    https://github.com/rgreinho/docopt-subcommands-example/blob/master/main.py

    #! /usr/bin/env python
    """
    Control center for an imaginary video game.
    usage:
        control [-hv] [-n NAME] <command> [<args>...]
    options:
        -h, --help                  shows the help
        -n NAME --name=NAME         sets player name [default: player]
        -v, --version               shows the version
    The subcommands are:
        greet   greets other players
        jump    makes the player jump
        run     makes the player run
    """
    
    from docopt import docopt
    from docopt import DocoptExit
    
    import commands
    
    if __name__ == '__main__':
        args = docopt(__doc__, version='1.0.0', options_first=True)
    
        # Retrieve the command to execute.
        command_name = args.pop('<command>').capitalize()
    
        # Retrieve the command arguments.
        command_args = args.pop('<args>')
        if command_args is None:
            command_args = {}
    
        # After 'poping' '<command>' and '<args>', what is left in the args dictionary are the global arguments.
    
        # Retrieve the class from the 'commands' module.
        try:
            command_class = getattr(commands, command_name)
        except AttributeError:
            print('Unknown command. RTFM!.')
            raise DocoptExit()
    
        # Create an instance of the command.
        command = command_class(command_args, args)
    
        # Execute the command.
        command.execute()

    https://github.com/rgreinho/docopt-subcommands-example/blob/master/commands.py

    from docopt import docopt
    
    
    class AbstractCommand:
        """Base class for the commands"""
    
        def __init__(self, command_args, global_args):
            """
            Initialize the commands.
            :param command_args: arguments of the command
            :param global_args: arguments of the program
            """
            self.args = docopt(self.__doc__, argv=command_args)
            self.global_args = global_args
    
        def execute(self):
            """Execute the commands"""
            raise NotImplementedError
    
    
    class Run(AbstractCommand):
        """
        Defines how long a player will run.
        usage:
            run ( --distance=<meters> | --time=<seconds> )
        options:
            --distance=<meters>     Player runs for <meters> meters.
            --time=<seconds>        Player run for <seconds> seconds.
        """
    
        def execute(self):
            if self.args['--distance']:
                if int(self.args['--distance']) > 100:
                    print('Are you crazy? {} is not going to do that!'.format(self.global_args['--name']))
                    return
                print('{} is going to run {} meters.'.format(self.global_args['--name'], self.args['--distance']))
            elif self.args['--time']:
                if int(self.args['--time']) > 10:
                    print('Are you crazy? {} not going to do that!'.format(self.global_args['--name']))
                    return
                print('{} is going to run for {} seconds.'.format(self.global_args['--name'], self.args['--time']))
    
    
    class Jump(AbstractCommand):
        """
        Defines how far a player will jump.
        usage:
            jump --distance=<meters>
        options:
            --distance=<meters>     Player jumps for <meters> meters.
        """
    
        def execute(self):
            print('{} is going to jump {} meters.'.format(self.global_args['--name'], self.args['--distance']))
    
    class Greet(AbstractCommand):
        """
        Greets others players.
        usage:
            greet
        """
    
        def execute(self):
            print('Hi other player(s)!')

    HUG

    https://hugapi.github.io/hug/

    亮点是, 一个库, 对CLI和API通吃。

    hug aims to make developing Python driven APIs as simple as possible, but no simpler. As a result, it drastically simplifies Python API development.

    hug's Design Objectives:

    • Make developing a Python driven API as succinct as a written definition.
    • The framework should encourage code that self-documents.
    • It should be fast. A developer should never feel the need to look somewhere else for performance reasons.
    • Writing tests for APIs written on-top of hug should be easy and intuitive.
    • Magic done once, in an API framework, is better than pushing the problem set to the user of the API framework.
    • Be the basis for next generation Python APIs, embracing the latest technology.

    As a result of these goals, hug is Python 3+ only and built upon Falcon's high performance HTTP library

    import hug
    
    
    @hug.get()
    def hello(request):
        """Says hellos"""
        return "Hello Worlds for Bacon?!"
  • 相关阅读:
    rapidjson解析
    约瑟夫环
    [易学易懂系列|rustlang语言|零基础|快速入门|(29)|实战6:BDD工具cucumber_rust]
    [易学易懂系列|rustlang语言|零基础|快速入门|(28)|实战5:实现BTC价格转换工具]
    [易学易懂系列|rustlang语言|零基础|快速入门|(27)|实战4:从零实现BTC区块链]
    [易学易懂系列|rustlang语言|零基础|快速入门|(26)|实战3:Http服务器(多线程版本)]
    [易学易懂系列|rustlang语言|零基础|快速入门|(26)|实战3:Http服务器]
    [易学易懂系列|rustlang语言|零基础|快速入门|(25)|实战2:命令行工具minigrep(2)]
    [易学易懂系列|rustlang语言|零基础|快速入门|(24)|实战2:命令行工具minigrep(1)]
    [易学易懂系列|rustlang语言|零基础|快速入门|(23)|实战1:猜数字游戏]
  • 原文地址:https://www.cnblogs.com/lightsong/p/16839404.html
Copyright © 2020-2023  润新知