3 个 Python 命令行工具

在本月的 Python 专栏中,学习如何使用 Click、Docopt 和 Fire 库编写您自己的命令行应用程序。
309 位读者喜欢这篇文章。
Tools in a tool box

Peter 的照片 (CC BY-SA 2.0),由 Rikki Endsley 修改

有时,完成工作的正确工具是命令行应用程序。 命令行应用程序是您可以与之交互并从 shell 或终端等运行的程序。 您可能已经熟悉 GitCurl 等命令行应用程序。

当您想要连续多次或定期运行一段代码时,命令行应用程序非常有用。 Django 开发人员运行 ./manage.py runserver 等命令来启动他们的 Web 服务器; Docker 开发人员运行 docker-compose up 来启动他们的容器。 您可能想要编写命令行应用程序的原因与您可能想要编写代码的原因一样多种多样。

对于本月的 Python 专栏,我们有三个库要推荐给希望编写自己的命令行工具的 Pythonistas。

Click

Click 是我们最喜欢的用于命令行应用程序的 Python 包。 它

  • 具有包含示例的出色文档
  • 包含将您的应用程序打包为 Python 应用程序的说明,以便更易于运行
  • 自动生成有用的帮助文本
  • 允许您堆叠可选和必需的参数,甚至 多个命令
  • 具有用于编写管理命令的 Django 版本 (django-click)

Click 使用其 @click.command() 将函数声明为命令并指定必需或可选的参数。

# hello.py
import click 

@click.command()
@click.option('--name', default='', help='Your name')
def say_hello(name):
    click.echo("Hello {}!".format(name))

if __name__ == '__main__':
    say_hello()

@click.option() 装饰器声明一个 可选参数@click.argument() 装饰器声明一个 必需参数。 您可以通过堆叠装饰器来组合可选和必需的参数。 echo() 方法将结果打印到控制台。

$ python hello.py --name='Lacey'
Hello Lacey!

Docopt

Docopt 是一个命令行应用程序解析器,有点像命令行应用程序的 Markdown。 如果您喜欢在编写应用程序时编写文档,那么 Docopt 在本文中提供的选项中具有格式最好的帮助文本。 它不是我们最喜欢的命令行应用程序库,因为它的文档会立即将您推入深水区,这使得入门有点困难。 尽管如此,它是一个轻量级的库,非常流行,尤其是在异常漂亮的文档对您很重要的情况下。

Docopt 非常特别,您需要以特定的方式格式化文件顶部的必需文档字符串。 文档字符串中工具名称之后的顶部元素必须是“Usage”,它应列出您希望命令被调用的方式(例如,单独调用、带有参数调用等)。 用法应包括 helpversion 标志。

文档字符串中的第二个元素应为“Options”,它应提供有关您在“Usage”中标识的选项和参数的更多信息。 文档字符串的内容将成为帮助文本的内容。

"""HELLO CLI

Usage:
    hello.py
    hello.py <name>
    hello.py -h|--help
    hello.py -v|--version

Options:
    <name>  Optional name argument.
    -h --help  Show this screen.
    -v --version  Show version.
"""

from docopt import docopt

def say_hello(name):
    return("Hello {}!".format(name))


if __name__ == '__main__':
    arguments = docopt(__doc__, version='DEMO 1.0')
    if arguments['<name>']:
        print(say_hello(arguments['<name>']))
    else:
        print(arguments)

在其最基本的层面上,Docopt 旨在将您的参数作为键值对返回到控制台。 如果我在不指定名称的情况下调用上述命令,我会得到一个字典

$ python hello.py 
{'--help': False,
 '--version': False,
 '<name>': None}

这表明我没有输入 helpversion 标志,并且 name 参数为 None

但是如果我使用名称调用它,say_hello 函数将执行。

$ python hello.py Jeff
Hello Jeff!

Docopt 允许必需参数和可选参数,并且每种参数都有不同的语法约定。 必需参数应以 ALLCAPS<尖括号> 表示,选项应以双破折号或单破折号表示,例如 --name。 在文档中阅读有关 Docopt 模式的更多信息。

Fire

Fire 是一个用于编写命令行应用程序的 Google 库。 当您的命令需要采用更复杂的参数或处理 Python 对象时,我们特别喜欢它,因为它会尝试智能地处理解析您的参数类型。

Fire 的 文档包含大量示例,但我希望文档的组织性更好一些。 Fire 可以处理 一个文件中的多个命令,作为 对象的方法的命令和 分组命令。

它的缺点是它向控制台提供的文档。 命令上的文档字符串不会出现在帮助文本中,并且帮助文本不一定标识参数。

import fire


def say_hello(name=''):
    return 'Hello {}!'.format(name)


if __name__ == '__main__':
  fire.Fire()

参数是必需的还是可选的,取决于您是否在函数或方法定义中为它们指定了默认值。 要调用此命令,您必须指定文件名和函数名称,更像 Click 的语法

$ python hello.py say_hello Rikki
Hello Rikki!

您也可以将参数作为标志传递,例如 --name=Rikki

奖励:打包!

Click 包含有关使用 setuptools 打包命令的说明(并强烈建议您遵循这些说明)。

要打包我们的第一个示例,请将此内容添加到您的 setup.py 文件

from setuptools import setup

setup(
    name='hello',
    version='0.1',
    py_modules=['hello'],
    install_requires=[
        'Click',
    ],
    entry_points='''
        [console_scripts]
        hello=hello:say_hello
    ''',
)

在您看到 hello 的任何地方,替换您的模块名称,但省略 .py 扩展名。 在您看到 say_hello 的任何地方,替换您的函数名称。

然后,运行 pip install --editable 以使您的命令可用于命令行。

您现在可以像这样调用您的命令

$ hello --name='Jeff'
Hello Jeff!

通过打包您的命令,您可以省略在控制台中键入 python hello.py --name='Jeff' 的额外步骤,并节省多次击键。 这些说明可能也适用于我们提到的其他库。

User profile image.
Jeff Triplett 是一名开源开发人员,并担任 REVSYS 的软件工程师、顾问和合伙人。 他是 Python 软件基金会的董事会成员。 他偶尔在他的网站上发表博客。
User profile image.
Lacey Williams Henschel 是 REVSYS 的一名软件工程师,并且是 DjangoCon US 的组织团队成员。 过去,她曾担任 DjangoCon US 的主席,组织了几个 Django Girls 研讨会,为 Treehouse 授课,并撰写了有关技术活动中的可访问性的文章。

2 条评论

我唯一要指出的是,在其默认状态下,Python 是一种命令行工具。 您只需要一个文本编辑器和一些编写脚本的练习。

我想添加另一个工具,其精神与 google 的 Fire 类似。
这是一个更简单的库(更易于使用,并且代码库更小)。

mach.py (用德语完成) 允许你写

from mach import mach1

@mach1
class Hello

default = 'greet'

def greet(self, name: str="")
if not name
name = input('您的名字: ')
print("你好 %s" % name)

if __name__ == '__main__'
Hello().run()

查看 http://mach.readthedocs.io/en/latest/ 以获取更多示例。

Creative Commons License此作品已根据知识共享署名 - 相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.