我覺得argparse中的sub_parsers有一個小小的限制,如果說,你有一套工具可能有類似的選項,可能在不同層次上傳播。出現這種情況可能很少,但如果您正在編寫可插拔/模塊化代碼,則可能會發生。
我有下面的例子。它是牽強和目前沒有得到很好的解釋,因爲它是比較晚的,但這裏有雲:
Usage: tool [-y] {a, b}
a [-x] {create, delete}
create [-x]
delete [-y]
b [-y] {push, pull}
push [-x]
pull [-x]
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument('-x', action = 'store_true')
parser.add_argument('-y', action = 'store_true')
subparsers = parser.add_subparsers(dest = 'command')
parser_a = subparsers.add_parser('a')
parser_a.add_argument('-x', action = 'store_true')
subparsers_a = parser_a.add_subparsers(dest = 'sub_command')
parser_a_create = subparsers_a.add_parser('create')
parser_a_create.add_argument('-x', action = 'store_true')
parser_a_delete = subparsers_a.add_parser('delete')
parser_a_delete.add_argument('-y', action = 'store_true')
parser_b = subparsers.add_parser('b')
parser_b.add_argument('-y', action = 'store_true')
subparsers_b = parser_b.add_subparsers(dest = 'sub_command')
parser_b_create = subparsers_b.add_parser('push')
parser_b_create.add_argument('-x', action = 'store_true')
parser_b_delete = subparsers_b.add_parser('pull')
parser_b_delete.add_argument('-y', action = 'store_true')
print parser.parse_args(['-x', 'a', 'create'])
print parser.parse_args(['a', 'create', '-x'])
print parser.parse_args(['b', '-y', 'pull', '-y'])
print parser.parse_args(['-x', 'b', '-y', 'push', '-x'])
輸出
Namespace(command='a', sub_command='create', x=True, y=False)
Namespace(command='a', sub_command='create', x=True, y=False)
Namespace(command='b', sub_command='pull', x=False, y=True)
Namespace(command='b', sub_command='push', x=True, y=True)
正如你所看到的,這是很難區分每個參數沿鏈設置的位置。 您可以通過更改每個變量的名稱來解決此問題。例如,您可以將'dest'設置爲'x','a_x','a_create_x','b_push_x'等,但這會很痛苦,很難分離出來。
另一種方法是讓ArgumentParser在到達子命令後停止並將其餘的參數傳遞給另一個獨立的分析器,以便它可以生成單獨的對象。 您可以嘗試通過使用'parse_known_args()'而不是爲每個子命令定義參數來實現。但是,這並不好,因爲之前未解析的參數仍然存在,並可能會使程序混淆。
我覺得有點便宜,但有用的解決方法是讓argparse將下列參數解釋爲列表中的字符串。這可以通過將前綴設置爲空終止符'\ 0'(或其他'難以使用'的字符)來完成 - 如果前綴爲空,那麼代碼會拋出一個錯誤,至少在Python 2.7中。 3。
實施例:
parser = ArgumentParser()
parser.add_argument('-x', action = 'store_true')
parser.add_argument('-y', action = 'store_true')
subparsers = parser.add_subparsers(dest = 'command')
parser_a = subparsers.add_parser('a' prefix_chars = '\0')
parser_a.add_argument('args', type = str, nargs = '*')
print parser.parse_args(['-xy', 'a', '-y', '12'])
輸出:
Namespace(args=['-y', '12'], command='a', x=True, y=True)
注意,它不消耗第二-y
選項。 然後,您可以將結果'args'傳遞給另一個ArgumentParser。
缺點:
- 幫助可能不能很好地處理。將不得不採取更多的解決方法
- 遇到錯誤可能很難追蹤,並需要一些額外的努力,以確保錯誤消息是正確鏈接。
- 與多個ArgumentParsers相關的一點額外開銷。
如果有人對此有更多意見,請告訴我。
公司我工作的有那麼使用argparse一個V2.6基線是,它必須被納入作爲外部庫,僅在需要時加載的問題。遠非不可能,只是不理想。至於cmdln庫,給我一些我不希望重新創建的基本功能。這就是說我反對使用別的東西。 – tima 2011-12-16 19:27:30