撰寫 Python CLI 工具並發佈到 PyPI

POSTED BY   Chris
2021 年 7 月 13 日
撰寫 Python CLI 工具並發佈到 PyPI

Python 除了在 ML 領域很紅外,在 DevOps 工具上也是滿多人用的,如很有名的 Ansible,就是以 Python 語言撰寫,再者如 AWS CLI,也是 Python 撰寫,所以這篇來介紹一下 CLI 套件工具,並且說明如何上傳到 pypi 後,經由 pip install 後,就可以有現成的 CLI 可以使用了

 

Python CLI 工具

Python CLI 工具非常的多,例如 這篇 有介紹不少工具,我是選用 PyInquirer,我想各個套件各有利弊,會選用這套的原因是因為語法很明暸易懂,馬上來看個例子

Python
questions = [
        {
            'type': 'list',
            'name': 'profile',
            'message': 'Choose one AWS Profile to set default',
            # 'choices': profiles.keys(),
            'choices': list(filter(lambda profile: True if profile.find(assume_role_profile_name) == -1 else False, list(profiles.keys())))
        },
        {
            'type': 'confirm',
            'name': 'assume_role',
            'message': 'Do you want to assume role for this profile?(Default false)',
            'default': False,
        },
        {
            'type': 'input',
            'name': 'role_name',
            'message': 'Input your role name to assume role?',
            'when': lambda answers: answers['assume_role']
        },
        {
            'type': 'input',
            'name': 'duration_seconds',
            'message': 'Input your maximum duration seconds of assume role?(Default 28800)',
            'when': lambda answers: answers['assume_role']
        },
    ]

answers = prompt(questions, style=custom_style_2)

is_assume_role = answers.get('assume_role')

只要定義好 dict ,帶入 prompt 中,輕鬆搞定,而取值就用 get 方法即可,很簡單,若 questions 中的目題有相依的需求,例如這個問題 user 回答 yes,才會有下一個問題繼續,在 PyInquirer 也很容易,如例子中,只有指定 when 的設定即可

想看這個效果,到我 GitHub repo Switch AWS Profile on local,README 就有 gif 動畫 demo 看效果,真的是輕鬆愉快,當然也還有更多進階的用法和選項,可到 PyInquirer GitHub repo 中看一下就知道

 

打包上傳至 PyPI

PyPI 就像 PHP 的 composer 或 node 的 npm 一樣,是發佈套件平台,讓全世界可以共用,而寫 CLI 的目的,當然希望可以安裝後直接下指令就能使用,以我自己的 Switch AWS Profile on local 為例,使用 pip 安裝如

pip3 install switch-aws-profile

馬上就有 awssp 指令可以使用,要想達到這個效果,首先要準備一下 setup.py 這個檔案,例如這樣設定

Python
from setuptools import setup, find_packages

with open("README.md", "r", encoding="utf-8") as fh:
    long_description = fh.read()
setup(
    name='switch-aws-profile',
    version='0.0.4',
    author='Chris Yang',
    author_email='kimisme9386@gmail.com',
    license='MIT',
    description='Switch AWS profile on local',
    long_description=long_description,
    long_description_content_type="text/markdown",
    url='https://github.com/kimisme9386/cli-switch-aws-profile',
    py_modules=['switch_profile'],
    packages=find_packages(),
    install_requires=['pyinquirer==1.0.3'],
    python_requires='>=3.7',
    classifiers=[
        "Programming Language :: Python :: 3.8",
        "Operating System :: OS Independent",
    ],
    entry_points='''
        [console_scripts]
        awssp=switch_profile.app:main
    ''',
    package_dir={'switch_profile': 'switch_profile'},
    package_data={'switch_profile': ['scripts/*.sh']},
)

大部分的設定都不難理解,特別要講的是 entry_points 這個設定,因為我們想要 pip3 install 後就能有安裝的指令可以用,所以使用 [console_scripts],而之後下一行也是重點

awssp=switch_profile.app:main

以此範例,awssp 就是你想要自訂的 command 名稱,而 switch_profile.app:main 也就是對應到 Python 的 package 和 modules 的概念,如 switch_profile 為資料夾下有 app.py 這個檔案,而 main 就是裡面的 function name

這邊也額外提一下,像這個範例,我是用 python 去 call 一個 Shell Script,所以這個 shell script 要能被找到才行,故設定上用 package_dirpackage_data 來處理這個部分,避免呼叫不到 shell script

設定好 setup.py 後,需要聲明這個套件的 LICENSE,可以到 choosealicense.com 選一個 LICENSE 複製貼上即可,到這邊後,就可以在本地測試看看

pipenv run python3 setup.py develop

看是用哪種 Python virtual environment 就怎麼用,這邊使用 pipenv 來當範例,若沒錯誤,在虛擬環境中的 bin 資料夾就會出現 awssp 這個指令可以使用

若測試無誤,再來就是打包和上傳了,首先若沒有 PyPI 帳號,需要去申請一個,之後就是先來打包

pipenv run python3 setup.py bdist_wheel

注意這邊也可以用 sdist 來完整使用原生 Python 打包就好,這邊我是選用 wheel 工具來打包,所以用 bdist_wheel,若執行沒問題,會產生 build 和 dist 兩個資料夾,再來就是上傳了

pipenv run twine upload dist/* -u __token__ -p ${PYPI_PASSWORD}

其中 ${PYPI_PASSWORD} 就是去 PyPI 後台新增 API tokens 後就會有的,這兩個指令我是寫在 GitHub Actions 上,可以參考這裡

若執行無誤,就可以到 PyPI 去看看發佈的狀況,之後修改程式碼想要再發佈新版本,只要修改 setup.py 中的 version,再執行這兩個指令,就能再度發版

 

結論

Python 語言雖然自己接觸沒像 PHP 那麼久,但跟 PHP 類似的是,要入門都是容易的,但要寫的好,那就是另外一回事了,要寫的好可以看一下 Real Python 的 Best practice,學習任何語言都需要花費不少功夫,才能真的寫的好,希望對 Python 有興趣的朋友都能開心入門,再持續精進

歡迎留言
0

您可能也想看