開發一款圖片壓縮工具(三):使用 click 實現命令列

和牛發表於2020-04-27

上一篇實現了圖片的壓縮函式。現在如果需要對圖片進行壓縮,可以呼叫實現的函式進行壓縮:

pngquant_compress('elephant.png', force=True, quality=20)

 

但是每次輸入 python run_script.py 沒有對應的引數傳入, 還要去改指令碼引數挺麻煩的。可以新增命令列的方式進行呼叫:

python run_script.py elephant.png --force --quality 30

 

1. 使用 click

python 的 click 庫可以非常方便的實現命令列呼叫。 click 是 flask 作者開發的。用法很簡單,只需要新增裝飾器在需要執行的程式上就可以了:

image.png

當我輸入 python demo.py —help 的時候, 會顯示命令列幫助資訊:

image.png

 

2. click 必填引數 argument

可以在函式上新增 @click.argument('arg_name')

import click
@click.argument("arg_name")
def pngquant_compress():

 

當程式沒有填入必填引數時,將會提示:

image.png

 

3. click 可選引數 option

option 是 click 的重點,比 argument 要靈活很多。他的表示方法和 argument 差不多:

import click
@click.option("--force")
def pngquant_compress():
    pass

 

如果想用多個名稱同時表示一個引數,只需要繼續在 option 方法中新增位置引數, 就可以通過 -f, --violent 的形式
傳入可選引數:

import click
@click.option("--force", "-f", "--violent")
def pngquant_compress():
    pass

 

如果不想以 --force value 的形式傳入值,也可以直接通過 flag 形式,不傳入任何值:

import click
@click.option("--force", "-f", "--violent", is_flag=True)
def pngquant_compress():
    pass

 

顯示提示資訊:

import click
@click.option(
    "--force", "-f", "--violent", 
    is_flag=True,
    help="強制執行"
    )
def pngquant_compress():
    pass

 

4. 引數型別限制

比如 quality 引數傳入的可以是數字 20, 也可以是 20-30 這種形式。這時候需要自定義一種資料型別進行校驗。

class QualityInteger(click.ParamType):
    name = "QualityInteger"

    def convert(self, value, param, ctx):
        if value.isdigit():
            return int(value)
        try:
            min_v, max_v = value.split('-')
            int(min_v), int(max_v)
            return value
        except ValueError:
            self.fail('引數不符合類似 20-30 或者 30 的規範')

 

此時如果輸入的引數沒有通過檢驗,命令列會提示錯誤:

\picom>python demo_06_封裝成命令列.py elephant.png -q 20-4a
Usage: demo_06_封裝成命令列.py [OPTIONS] FP

Error: Invalid value for "--quality" / "-q": 引數不符合類似 20-30 或者 30 的規範

 

5. setuptools 打包

from setuptools import setup, find_packages

setup(
    name='picom',
    version='0.1',
    install_requires=[
        'Click',
        'requests'
    ],
)

 

setup.cfg 配置檔案:

[metadata]
name = picom
description = A app to compress images.

[options]
packages = find:
package_dir = = src
include_package_data = true
python_requires = >= 3.6

[options.packages.find]
where = src

[options.entry_points]
console_scripts =
    picom = picom.cli:cli

 

把 picom 模組放入依賴包路徑,執行 pip install --editable . 可以安裝這個模組。
安裝完成以後,可以在 python 直譯器路徑看到 picom.exe 命令列檔案。建議建立虛擬環境安裝,以免對系統環境造成汙染。

image.png

 

6. 撤銷 pngquant 全域性變數,改由 picom 包內呼叫

之前在 pngquant_compress 函式中使用 pngquant 命令列是採用環境變數,現在既然是通過 picom 命令去執行,就可以把 pngquant
的環境變數去掉。

首先需要在 picom 包中新增一個 ext 的包存放 pngquant 的執行檔案。
image.png

修改原來的呼叫函式:

# pngquant.py

# 原來的寫法
command = f'pngquant {fp} --skip-if-larger {force_command} {quality_command}'

# 新寫法,直接呼叫 ext/ 下的可執行檔案,而不是環境變數中的 pngquant
pngquant_cmd = Path(__file__).resolve().parent / 'ext' / 'pngquant'
command = f'{pngquant_cmd} {fp} --skip-if-larger {force_command} {quality_command}'

 

7. 總結

通過 click 庫和 setuptool 打包,picom 壓縮工具使用變得比較簡單:

picom elephant.png

相關文章