2014-02-28 71 views
1

​​在組合標誌時給我不同的結果(-x -y>-xy)。這是很難用言語來解釋,所以我已經減少了問題以下最低設置:python:argparse中的奇怪錯誤行爲

# test.py 
def invalid_argument_type(x): 
    raise Exception("can't parse this") # in my code, it doesn't *always* fail 

parser = argparse.ArgumentParser() 

parser.add_argument('args', type = invalid_argument_type) 
parser.add_argument('-x') 

print parser.parse_args() 

現在,錯誤地調用這個程序產量意外的結果。第一個命令是正確的,第二個有一個無效的標誌,第三個應該是一樣的第二:

$ python test.py -x foo 
Namespace(args=[], x='foo') 

$ python test.py -A -x foo 
test.py: error: unrecognized arguments: -A 

$ python test.py -Ax foo 
Exception: can't parse this 

看來,當標誌組合,「未知的標誌」的錯誤吞下-xfoo被視爲一個常規論證。請注意,如果-A標誌存在,則-A-x在任何情況下均可按預期工作。

這會導致高度混淆的錯誤消息。

我是否使用​​錯誤?有沒有辦法解決這個問題,還是應該將錯誤處理移到我自己手中?

回答

1

您看到了這一點,因爲在參數解析期間發生的異常比簡單的參數錯誤重要。解析的參數確實認識到-Ax是一個無效標誌,並且只是記錄稍後顯示的標誌;但由於args的解析失敗並出現異常,因此該異常立即顯示,而其他無效參數則不再提及。

您也可以從源中確認此行爲。 parse_args將把解析步驟委託給parse_known_args,該步驟返回解析的名稱空間和無效參數列表。然而,parse_known_args會在內部嘗試解析它,並在出現異常時立即顯示。因此,異常會在parse_args顯示無效參數之前中止該過程。

現在,你們三個例子的工作方式都不一樣,這就是爲什麼你只看到最後一個例外。因此,讓我們檢查他們詳細:

  • -x foo:在這裏,-x是一個有效的參數名稱,foo是該值。所以一切都很好。
  • -A -x foo-A是一個無法識別的參數,所以記下來。其餘的部分是-x foo,這也是參數x的有效序列。
  • -Ax foo-Ax是一個無法識別的參數,所以再次記錄下來。其餘部分是foo。由於沒有參數標誌,解析器會嘗試將其與args參數相匹配 - 這會引發異常。

注意argparse只做支持相結合的標誌(-Ax)如果能正確解析那些由左到右。由於單短劃線標誌也可能長於一個字符(例如-foo會很好),所以不能安全地說-Ax將爲-A -x,因爲您實際上可能已經定義了-Ax參數。爲了能夠做出這個聲明,它實際上將開始解析-Ax,它將首先嚐試找到與之匹配的參數。由於沒有-A參數,它假定它應該是-Ax。但那也不存在,所以它在那裏失敗了。

+0

但是當標誌有效時,組合標誌似乎工作正常:( – slezica

+0

是的,你是對的,稍微更新我的答案。基本上,它不能開始與任何已知參數匹配'-Ax',所以它不會不知道在哪裏分開它,因此,它根本不會這樣做,並且將整個'-Ax'標記爲無效。 – poke

+0

我將減少'argparse'的責任,並在 – slezica