【💊 Python的解憂錦囊】Click如何驗證參數?

閱讀時間約 4 分鐘
raw-image


我們在「【🔒 Python 先修班】👆 打造友善的使用者互動CLI介面」有介紹Python的Click命令列參數設計介面的方式, 那我們除了設計出介面提供使用者互動之外, 有時候也需要一點驗證機制, 畢竟我們心裡都清楚「garbage in, garbage out」的後果, 為了減少這種狀況, 我們針對一些非常重要的參數就會需要來點驗證, 但Click可以怎麼做呢?

善用Callbacks來自訂驗證函數

click的@option參數中有一個參數是callback, 也就是當使用者輸入參數後進行呼叫的函數, 此時我們就可以在該函數進行驗證的邏輯檢查, 避免用戶輸入到有害的資料造成不必要的麻煩, 並且我們可以引發「BadParameter」來告知使用者哪裡錯了。

訊息的呈現會進行自動化格式, 大致如下:

Error: Invalid value for '--val': 錯誤訊息

那麼首先我們可以設計一個validate的函數來驗證輸入值必須小於100且為整數:

import click

def validate(ctx: click.Context, param: click.Parameter, value: int) -> int:
"""驗證整數必須小於100

"""
try:
if value > 100:
raise ValueError(f'您輸入的值為 {value} 必須小於等於 100')

return value
except ValueError as e:
raise click.BadParameter(
e,
ctx,
param,
)

接著我們在click.option可以掛入該函數:

@click.command()
@click.option(
"--val",
type=click.INT,
callback=validate,
)
def run(**options):
print(options)

run()

最後我們稍微來測試一下幾個情境

首先是輸入非整數的部份, 將出現以下的錯誤訊息:

python test.py --val str

# 出現的訊息如下:
Usage: test.py [OPTIONS]
Try 'test.py --help' for help.

Error: Invalid value for '--val': 'str' is not a valid integer.

再來是輸入101看看是否會出現我們預期的錯誤訊息:

python test.py --val 101

# 出現的訊息如下:
Usage: test.py [OPTIONS]
Try 'test.py --help' for help.

Error: Invalid value for '--val': 您輸入的值為 101 必須小於等於 100

最後測試一下合法的輸入值:

python test.py --val 5

# 出現以下參數訊息
{'val': 5}

結語

Python的click套件對於設計CLI介面來說真的非常的方便, 除了提供基本的參數驗證機制之外, 也讓我們高度客製化我們的驗證機制, 讓我們面對於各種使用者時有一個統一的標準介面, 並且提供足夠的訊息來導引使用者填入正確的參數, 也避免我們後續作業上的資料錯誤與複雜度, 如果您還不知道Python的click套件, 那麼我們會推薦您以下的文章進行學習:

avatar-img
118會員
264內容數
哈囉,我是阿Han,是一位 👩‍💻 軟體研發工程師,喜歡閱讀、學習、撰寫文章及教學,擅長以圖代文,化繁為簡,除了幫助自己釐清思路之外,也希望藉由圖解的方式幫助大家共同學習,甚至手把手帶您設計出高品質的軟體產品。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
阿Han的沙龍 的其他內容
Python雖然是直譯式的腳本語言, 用起來非常方便, 但當我們的工具越發成熟時, 就會需要將使用方式、介面給設計好, 那通常都會用來處理後端伺服器的作業, 也比較面向IT端, 因此我們通常會以Command Line的形式與使用工具的人進行互動, 而內建模組雖然有「argparse」可以讓我們
排序這個動作在軟體開發中常常會使用到, 從使用者期望所見的順序到資料處理的效能議題都與排序息息相關, 因此掌握程式語言的排序功能是非常重要的一個環節, 而我們在閱讀他人的Go專案程式碼時也會看到排序的方式有些許不同, 那究竟有何差異呢? 就讓我們繼續看下去吧… 其實在進入今天的主題之前, 我們
我們在「【🔒 Python 先修班】⬆️ 培養良好的Coding Style讓專業度 Up!Up!Up!」談到了Coding Style, 在文末也分享了pylint的程式碼檢查工具, 雖然內建、簡單快速上手, 但隨著技術的演進, 我們總需要又快、又好、又簡單的工具做為預設的工具庫, Ruff
撰寫Python的朋友都知道multithread/multiprocess能為我們帶來效能的改進,減少硬體資源的閒置,但在撰寫的過程中常常會發現到我們所設計的工作池模式會需要將「待辦清單」的工作項目當成參數傳遞進去執行, 除了「待辦清單」之外, 其餘的參數基本上都是固定的, 基於這樣的需求之下
我們在「【💊 Python的解憂錦囊】如何將dict轉成json並儲存」有介紹過如何將dict型態的資料轉換成json,除了json之外, 另一個耳熟能詳的資料交換格式就是csv了, 我們常常會將csv讀進來, 並使用預先設計的@dataclass來存放, 如此一來實際運行時, 更能夠貼近於我
關於json的資料交換格式請參考「【程式語言 - Javascript】輕量資料格式 JSON」, 我們常常會在使用套件的過程中發現回傳值的型態都會有「dict」的蹤跡, 為什麼呢? 因為動態、彈性、靈活, 不需要預先定義類別來明確指定每個欄位的內容, 但缺點就是文件必須寫清楚內容物是哪些, 否
Python雖然是直譯式的腳本語言, 用起來非常方便, 但當我們的工具越發成熟時, 就會需要將使用方式、介面給設計好, 那通常都會用來處理後端伺服器的作業, 也比較面向IT端, 因此我們通常會以Command Line的形式與使用工具的人進行互動, 而內建模組雖然有「argparse」可以讓我們
排序這個動作在軟體開發中常常會使用到, 從使用者期望所見的順序到資料處理的效能議題都與排序息息相關, 因此掌握程式語言的排序功能是非常重要的一個環節, 而我們在閱讀他人的Go專案程式碼時也會看到排序的方式有些許不同, 那究竟有何差異呢? 就讓我們繼續看下去吧… 其實在進入今天的主題之前, 我們
我們在「【🔒 Python 先修班】⬆️ 培養良好的Coding Style讓專業度 Up!Up!Up!」談到了Coding Style, 在文末也分享了pylint的程式碼檢查工具, 雖然內建、簡單快速上手, 但隨著技術的演進, 我們總需要又快、又好、又簡單的工具做為預設的工具庫, Ruff
撰寫Python的朋友都知道multithread/multiprocess能為我們帶來效能的改進,減少硬體資源的閒置,但在撰寫的過程中常常會發現到我們所設計的工作池模式會需要將「待辦清單」的工作項目當成參數傳遞進去執行, 除了「待辦清單」之外, 其餘的參數基本上都是固定的, 基於這樣的需求之下
我們在「【💊 Python的解憂錦囊】如何將dict轉成json並儲存」有介紹過如何將dict型態的資料轉換成json,除了json之外, 另一個耳熟能詳的資料交換格式就是csv了, 我們常常會將csv讀進來, 並使用預先設計的@dataclass來存放, 如此一來實際運行時, 更能夠貼近於我
關於json的資料交換格式請參考「【程式語言 - Javascript】輕量資料格式 JSON」, 我們常常會在使用套件的過程中發現回傳值的型態都會有「dict」的蹤跡, 為什麼呢? 因為動態、彈性、靈活, 不需要預先定義類別來明確指定每個欄位的內容, 但缺點就是文件必須寫清楚內容物是哪些, 否
你可能也想看
Google News 追蹤
Thumbnail
就如同標題一樣,input的作用就是從使用者那裡獲取輸入,直到使用者輸入一段文本並按下 ENTER 鍵。 然而用戶輸入的數據(文本)都將作為字串被返回,並存儲在變數中。 接著我們舉個例,比如說我們在一段數據中需要獲取使用者的名稱,範例如下: name = input("請輸入你的名字:") #
在處理數據時,最可能會遇到數據中含有None的時候,若沒有處理就進行運算就會造成程式崩潰或者報錯 數據中含有None input_list = [(42, 292), (28, 296), (999, 92), (993, 46), (219, 4), (279, 2), (None, None
在檢查列表中含有tuple的座標點時,若要給其他演算法做運算時若有其中有tuple有空值時,就會報錯。 本文主要介紹兩種方法可以檢查是否有空值 程式範例1 positon_list =[(42,123),(None,None),(22,11)] for cord in positon_lis
Thumbnail
Python語法包括條件語句、迴圈、函數和變數的使用。條件語句如if、elif和else用於進行條件判斷,for和while是兩種主要的迴圈,def用於定義函數。變數可以被賦予數字或字符串,並可使用類型提示來指定變數的類型。註解可以是單行或多行,並可用於解釋函數或類的用途和作用。
Thumbnail
在實務上,若Python報錯時,若引入的套件越多伴隨的異常訊息會變得越來越複雜,看到一推密密麻麻的內容時,很多時候都想直接跳過。 本文將利用Traceback來讓異常訊息變得更好理解。
Thumbnail
讀取ini配置文件時如果某個參數不存在,它就會報錯,要怎麼避免呢? 可以使用fallback 參數來指定預設值。 這樣即使配置文件中缺少一些參數,我們的程序也能正常運行並使用預設值。 讓我們來假設一個案例做說明: 先故意將先前範例的port的資料刪掉。
Thumbnail
當我們在做很多處理時,結果可能會是List包住一些數值,例如找輪廓或連通域分析時,沒有剛好的特徵可能就會有List含(空值得)形式出現。 為了避免報錯,我們就要額外先做一些處理,先做判斷是否有值在往下一個階段。 all 和 any 是 Python 中用於檢查可迭代物件(如清單、元組、集合等)
Thumbnail
本文介紹了Python中函式引數的*args和**kwargs用法,通過*args處理可變數量的位置引數,通過**kwargs處理可變數量的關鍵字引數。不僅介紹了相應的語法和程式範例,還解釋了它們的順序問題和建議的慣例用法。
Thumbnail
本文介紹Python程式設計中處理異常的try, except, else, finally語句,並提供程式範例來更深刻理解使用方法。
Thumbnail
就如同標題一樣,input的作用就是從使用者那裡獲取輸入,直到使用者輸入一段文本並按下 ENTER 鍵。 然而用戶輸入的數據(文本)都將作為字串被返回,並存儲在變數中。 接著我們舉個例,比如說我們在一段數據中需要獲取使用者的名稱,範例如下: name = input("請輸入你的名字:") #
在處理數據時,最可能會遇到數據中含有None的時候,若沒有處理就進行運算就會造成程式崩潰或者報錯 數據中含有None input_list = [(42, 292), (28, 296), (999, 92), (993, 46), (219, 4), (279, 2), (None, None
在檢查列表中含有tuple的座標點時,若要給其他演算法做運算時若有其中有tuple有空值時,就會報錯。 本文主要介紹兩種方法可以檢查是否有空值 程式範例1 positon_list =[(42,123),(None,None),(22,11)] for cord in positon_lis
Thumbnail
Python語法包括條件語句、迴圈、函數和變數的使用。條件語句如if、elif和else用於進行條件判斷,for和while是兩種主要的迴圈,def用於定義函數。變數可以被賦予數字或字符串,並可使用類型提示來指定變數的類型。註解可以是單行或多行,並可用於解釋函數或類的用途和作用。
Thumbnail
在實務上,若Python報錯時,若引入的套件越多伴隨的異常訊息會變得越來越複雜,看到一推密密麻麻的內容時,很多時候都想直接跳過。 本文將利用Traceback來讓異常訊息變得更好理解。
Thumbnail
讀取ini配置文件時如果某個參數不存在,它就會報錯,要怎麼避免呢? 可以使用fallback 參數來指定預設值。 這樣即使配置文件中缺少一些參數,我們的程序也能正常運行並使用預設值。 讓我們來假設一個案例做說明: 先故意將先前範例的port的資料刪掉。
Thumbnail
當我們在做很多處理時,結果可能會是List包住一些數值,例如找輪廓或連通域分析時,沒有剛好的特徵可能就會有List含(空值得)形式出現。 為了避免報錯,我們就要額外先做一些處理,先做判斷是否有值在往下一個階段。 all 和 any 是 Python 中用於檢查可迭代物件(如清單、元組、集合等)
Thumbnail
本文介紹了Python中函式引數的*args和**kwargs用法,通過*args處理可變數量的位置引數,通過**kwargs處理可變數量的關鍵字引數。不僅介紹了相應的語法和程式範例,還解釋了它們的順序問題和建議的慣例用法。
Thumbnail
本文介紹Python程式設計中處理異常的try, except, else, finally語句,並提供程式範例來更深刻理解使用方法。