簡體   English   中英

Argparse:檢查是否傳遞了任何參數

[英]Argparse: Check if any arguments have been passed

當沒有給出參數時,我的腳本應該啟動演示模式。 我試過這個:

args = parser.parse_args()
if len(args) == 0:
    run_demo()
else:
    # evaluate args

這給出了*** TypeError: object of type 'Namespace' has no len() as args is no list。

我將如何實現我想要的?

如果您的目標是檢測何時沒有給命令提供任何參數,那么通過argparse執行此操作是錯誤的方法(正如 Ben 很好地指出的那樣)。

想簡單! :-) 我相信 argparse 不會減少sys.argv 因此, if not len(sys.argv) > 1 ,則用戶未提供任何參數。

argparse 允許您根據您的規范和正在解析的命令行設置(在 Namespace 對象內)您添加到解析器的參數中提到的所有變量。 如果您設置了默認值,那么如果在命令行上沒有看到這些變量,它們將具有該默認值,它們不會出現在 Namespace 對象中。 如果您指定默認值,則有一個隱式默認值None 因此,檢查 Namespace 對象的長度,無論您設法做什么,作為檢查是否解析任何參數的方法都沒有意義; 它應該始終具有相同的長度。

相反,如果你知道你有一堆沒有默認值的參數,並且你想檢查它們中的任何一個是否被設置為任何非None值......這樣做。 您可以使用列表理解和vars函數來循環它們,而不必復制來自add_argument調用的名稱列表,如 Martijn 的回答所示。

如果您的某些參數具有默認值,則會變得有點棘手,如果它們具有可以在命令行上顯式提供的默認值(例如,默認為 0 的數字參數使得無法從用戶那里得知默認值)提供 0)。 在那種情況下,我不確定是否有一個通用的解決方案,在不知道參數是什么的情況下總是有效。

如果確實需要參數編號(無論出於何種原因)。 我發現這段代碼非常有幫助(但不知道它優化了多少,我很感激對它的任何評論)。

args = parser.parse_args()
print( len( vars(args) ) )

此版本僅計算 -xx 參數,而不計算傳遞的任何其他值。

如果你想要一切(還有傳遞的值),那么只需使用前面提到的len(sys.argv)

不要使用 argparse。 而是使用sys.argv argparse創建一個命名空間,因此它總是會為您提供一個帶有它們的值的“字典”,具體取決於您在調用腳本時使用的參數。

這是我過去所做的:

args = parser.parse_args()
if len(sys.argv) == 1:
    parser.print_help()
    sys.exit()
return args

我知道這是一個舊線程,但我找到了一個更直接的解決方案,可能對其他人也有用:

您可以檢查是否已傳遞任何參數:

if any(vars(args).values()):
    # evaluate args

或者,如果沒有傳遞參數(注意not運算符):

if not any(vars(args).values()):
    run_demo()

解釋:

  • parse_args()返回一個包含每個參數名稱及其關聯值的“命名空間”對象。 示例: Namespace(arg1='myfile.txt', arg2='some/path/to/some/folder')

  • 如果沒有傳遞參數parse_args()將返回相同的對象,但所有值都為None 示例: Namespace(arg1=None, arg2=None)

但是,此對象不可迭代,因此您必須使用vars()將其轉換為dict以便我們可以訪問這些值。

最后,因為我們現在手頭有一個dict ,我們可以使用.values()獲取所有值(在list .values() ,並使用內置的any()函數來檢查是否有任何值不是None 為了更清楚:如果在您提供給它的列表中沒有一個值不是NoneFalse0 (檢查文檔以供參考), any()將返回False

希望能幫助到你。

讓我們假設以下示例來擴展您的完整性:

#!/usr/bin/env python3

import argparse

...
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('input', nargs='?' action='store')
    parser.add_argument('-l', '--length', type=int, action='store')
    parser.add_argument('-v', '--verbose', action='store_true')
    args = parser.parse_args()
    if (args.input == None and args.length == None):
        parser.print_help()
    else:
        print(args)

if __name__ == '__main__':
    main()

@Ben 提到的 Namespace 對象在本例中是args parser.add_argument的字符串創建一個變量。 您可以通過args.inputargs.lengthargs.verbose訪問它。 您可以通過執行print(args)來驗證這一點,它實際上會顯示如下內容:

Namespace(input=None, length=None, verbose=False)

由於 verbose 設置為True ,如果存在,輸入和長度只是變量,不必實例化(不提供參數)。

如果您想確保不能同時提供兩個屬性,也可以使用group = parser.add_mutually_exclusive_group()

如需進一步參考,請參閱:

我擴展了 2dvisio 的概念來計算非零或無參數:

vm_opts = parser.parse_args()
v = vars(vm_opts)
n_args = sum([ 1 for a in v.values( ) if a])

對於最簡單的情況,您要檢查是否傳遞了所有輸入中相同的單一類型的參數,您可以使用argparsenumpy分三步完成。

import argparse
import numpy as np

args = parser.parse_args()
# namespace to dictionary
args_dict = vars(args)
# unpack values from dictionary, pass to array
values = np.array([*args_dict.values()])
# Check if the defaults have changed
args_indices = np.where(values != default)[0]
# Did we pass any arguments?
if len(values) == len(args_indices):
   print("No arguments were passed")

長度用作代理來檢查是否已傳遞任何沒有參數。 如果您想知道通過了哪一個,您可以打開密鑰並檢查更改后的索引。

np.array()接受用於更復雜情況的邏輯運算符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM