用python-fireð¥构建CLI迅速建造
#编程 #生产率 #python #cli

命令行应用程序是开发人员最好的朋友。想快速完成工作吗?只有几个击键,您已经有了要寻找的东西。

python是许多开发人员需要快速入侵一些开发人员的第一语言。但是,我们在大多数情况下都不是整个CLI,您需要管理标志,解析论点,链子子命令等,这很麻烦,因此会导致多个小型和不受管理的脚本。 /p>

在当今的文章中,我们将结束这一点,看看我们如何在不用任何精美的装饰器或任何东西的情况下在短短几分钟内建立合理的CLI。

创建和激活虚拟环境

python -m venv venv

source venv/bin/activate

# Install python-fire 🔥
pip install fire

您的第一个子命令

我们的CLI应用程序将是一堆工具的聚合,因此我们将其称为工具CLI。

使用python-fire,您可以使用功能或类创建子命令。但是我发现使用更直观和可管理的课程的工作。我们的第一个命令将是向我们显示UTC时间的子命令。

我们将创建一个新方法utc(),它将是我们的子命令,我们有一个称为pretty的参数,该参数将是我们的子命令的 flag ,它将UTC日期打印在更人性化的可读性中格式。 这个参数已经具有默认值,因此这不是必需的标志。

# tools.py

from datetime import datetime
import fire

class Tools:
    def utc(self, pretty: bool = False):
        """
        Get UTC date time
        """
        utc_time = datetime.utcnow()

        if pretty:
            ## strftime format codes:
            # https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
            print(utc_time.strftime("%B %d :: %H:%M %p"))
        else:
            print(utc_time)

接下来,我们需要将此文件作为脚本运行,因此在文件末尾我们需要添加以下内容:

if __name__ == "__main__":
    fire.Fire(Tools)

现在我们准备好了CLI!让我运行它!

python tools.py utc
python tools.py utc --pretty

# For help message
python tools.py

# For sub-command help message
python tools.py utc --help

Image description

通过所有这些开销python tools.py <command>输入键入有些不知所措;好吧,这甚至不像我希望能做的CLI。
您可能有以下问题:

  • 如何从我想要的任何位置调用它?
  • 我想将其命名为我发现直观的东西,我该怎么做?

为此您要为其创建一个发行版。

命令行的软件包ð

首先,我们需要对程序进行一些修改以适应包装:

# REMOVE THIS CHUNK
if __name__ == "__main__":
    fire.Fire(Tools)

# ADD THIS CHUNK
def run():
    fire.Fire(Tools)

现在,让我们创建一个setup.py文件来管理我们的包装/分发。您可以使用此文件作为参考来创建自己的CLI:

# setup.py
"""Package setup"""
import setuptools

# Development Requirements
requirements_dev = ["pytest", "black", "mypy", "flake8", "isort"]

setuptools.setup(
    name="tools_cli",
    version="0.0.1",
    author="Yankee Maharjan",
    url="https://yankee.dev/build-cli-blazingly-fast-with-python-fire",
    description="Collection of handy tools using CLI",
    license="MIT",
    packages=setuptools.find_packages(exclude=["dist", "build", "*.egg-info", "tests"]),
    install_requires=["fire"],
    extras_require={"dev": requirements_dev},
    entry_points={"console_scripts": ["to = tools:run"]},
)

您需要关注的行是entry_points,它将我们程序的入口点描述为控制台脚本。

entry_points={"console_scripts": ["to = tools:run"]},

在这里,to是我们CLI的名称,您可以将其命名为您喜欢的任何东西。如果您想将其命名为brr,它将像这样:

entry_points={"console_scripts": ["brr = tools:run"]},

tools:run表示我们模块的名称,然后是其需要运行的功能。控制台脚本总是需要一个函数来运行我们之前进行的修改。

感觉像一个cli

现在,让我们在虚拟环境中以可编辑模式安装我们的CLI。这就像为您的CLI重新加载,无论您进行的任何更改都会立即反映。

在您的项目目录中运行以下命令。

pip install -e .

现在,您可以使用命令to或在 console_scripts
上使用CLI

to utc
to utc --pretty
to utc --help

Image description

这很整洁!

现在如何确保我可以从我想要的任何位置运行它?

  • 停用您的虚拟环境:

    deactivate
    
  • 在您的全球站点包上再次以可编辑模式安装项目:

    pip install -e .
    

现在已经完成了,您将在整个系统中访问CLI。但是请注意,如果您对主要CLI逻辑进行任何更改,它将立即反映。

奖励:嵌套命令â€

如果您已经做到了这么远,那么您将准备自己的CLI并完成大多数用例。但是,如果您想更多地看到一些,请稍等一下。

让我们在我们的工具中添加其他命令,首先是一个名为leap()的子命令,该子命令验证给定的年度是否leap,最后是一个名为pw()的子命令,以生成一个强密码。

...
import calendar
import string
import secrets

class Tools:
    def utc(self, ...):
        ...

    def leap(self, year:int): # required: since no default value here
        """
        Check if given year is leap or not
        """
        print(calendar.isleap(year))

    def pw(self, len: int = 16):
        """
        Generate strong password
        """
        alphabet = string.ascii_letters + string.digits + string.punctuation
        pwd_length = len

        pwd = ""
        for i in range(pwd_length):
            pwd += "".join(secrets.choice(alphabet))

        print(pwd)

def run():
    fire.Fire(Tools)

现在运行命令

to leap 2022
to pw
to pw --len 22
to pw 25

Image description
有时,您想将相关的命令组合在一起,例如在我们的情况下,我们可以将utcleap分组在datetimedt之下。基本上我们想在这里做的是嵌套命令。

让我们的命令分组。我们将将我们的leap()utc()方法移到一个名为DateTime的新类中。

...

class DateTime:
    def utc(self, pretty: bool = False):
        """
        Get UTC time
        """

        from datetime import datetime

        utc_time = datetime.utcnow()

        if pretty:
            print(utc_time.strftime("%B %d :: %H:%M %p"))
        else:
            print(utc_time)

    def leap(self, year:int): # required: since no default value here
        """
        Check if given year is leap or not
        """
        print(calendar.isleap(year))

class Tools:
    def __init__(self):
        self.dt = DateTime()

    def pw(self, ...):
        ...

子命令是由我们在实例化新的DateTime类时将其作为可变名称所确定的。在这里,我们将其命名为dt,但您可以将其命名为datetimedtt或您想要的任何内容。

现在,我们有更多有组织的子命令为我们的CLI。如果要运行与日期时间相关的命令,则可以使用to dt <command-name>进行操作;例如:

to dt utc
to dt leap 2025

Image description

密码命令将是正常的:

to pw
to pw --len 30

结论

使用Python-Fire使创建CLI的过程非常简单,直观,因为您只使用Python功能和类。我希望该工具的迷你拆卸以及如何为您的日常使用打包它有所帮助。