2014-09-13 100 views
5

我有一個Python腳本,它運行兩個接受相同選項--config的子命令。我想創建第三個子命令,它們可以按順序一起運行前兩個子命令。對子命令中的選項argparse的衝突解析器將關鍵字參數變爲位置參數

使用argparse,我爲每個子命令以及第三個子分析器創建了一個子分析器,其父母是兩個子命令。只是爲了澄清:

subcommand1 = subparsers.add_parser('subcommand1') 
subcommand1.add_argument('--config', help="The config") 

subcommand2 = subparsers.add_parser('subcommand2') 
subcommand2.add_argument('--config', help="The config") 

wrappercommand = subparsers.add_parser('wrappercommand', 
             parents=[subcommand1, subcommand2], 
             conflict_handler='resolve') 

當我運行wrappercommand或subcommand2時,一切正常。然而,subcommand1休息,以此爲輸出:

$ run_command.py subcommand1 --config path_to_config.ini 

usage: run_command.py subcommand1 config 

optional arguments: 
    help     show this help message and exit 
    config    The config 

它看起來像argparse已經變成一個關鍵字ARG(「--config」)到的位置一(「配置」)。這是在argparse解決衝突選項時的預期行爲嗎?

+0

你能發佈完整的解析代碼嗎?該論據是否應該是「幫手」? – Forge 2014-09-13 02:11:35

+0

這是一個錯字 - 它應該是'help ='配置''。 – hpaulj 2014-09-13 18:10:26

回答

3

我認爲你正在將這個衝突處理程序推入無意和未經測試的領域。通常,parents是獨立的解析器,無法使用。他們只是Actions的來源。有關-h的衝突使用add_help=False進行處理。

通過背景:使用默認conflict_handler(錯誤)創建wrappercommand子分析器時,你會得到錯誤信息:

argparse.ArgumentError: argument -h/--help: conflicting option string(s): -h, --help 

,並增加了一些add_help=False之後,你仍然會得到:

argparse.ArgumentError: argument --config: conflicting option string(s): --config 

resolve衝突處理程序用某種「分辨率」替換錯誤消息。下面的腳本演示了正在發生的事情。

resolve處理程序刪除了option_stringssubcommand1的操作,同時使操作保持原位。實際上它將兩者都轉化爲定位。由於helpnargs=0,它總是運行。因此,幫助顯示。

_handle_conflict_resolve的意圖是去除第一個參數的證據,所以可以添加新的參數。當衝突由兩個add_argument命令產生並具有相同的選項字符串時,可以正常工作。但是這裏的衝突是由兩位父母的「複製」行爲產生的。但是父母的行爲通過引用被複制,所以'孩子'的變化最終影響'父母'。

一些可能的解決方案:

  • 參數添加到wrappercommand直接。這個parents機制只是增加了父母對孩子的爭論。它不會「連續」運行父母。

  • 編寫自己的_handle_conflict_...函數來正確解決衝突。

  • 刪除衝突,因此您可以使用parents而不使用resolve處理程序。


我已經提交給美國這個例子 http://bugs.python.org/issue22401一個bug報告:

parent1 = argparse.ArgumentParser(add_help=False) 
parent1.add_argument('--config') 
parent2 = argparse.ArgumentParser(add_help=False) 
parent2.add_argument('--config') 

parser = argparse.ArgumentParser(parents=[parent1,parent2], 
    conflict_handler='resolve') 

def foo(parser): 
    print [(id(a), a.dest, a.option_strings) for a in parser._actions] 

foo(parent1) 
foo(parent2) 
foo(parser) 

主要生產:

[(3077384012L, 'config', [])] 
[(3076863628L, 'config', ['--config'])] 
[(3076864428L, 'help', ['-h', '--help']), (3076863628L, 'config', ['--config'])] 

注意失蹤option_stringsparent1,並匹配id其他2. parent1不能再次使用,無論是作爲父級還是解析器。


argparse - Combining parent parser, subparsers and default values 是其中通過參考複製父母的動作產生的併發症(在改變的缺省值)另一種情況。

+0

謝謝,您的回覆在所有要點上都是正確的。我將直接添加選項到subparser而不使用'parents'機制。 – toothgrinder 2014-09-15 21:25:44