python庫介紹-argparse: 命令列選項及引數解析
快速入門
argparse是一個完整的引數處理庫。引數可以根據add_argument()的action選項觸發不同action。支援的action有儲存引數(單個,或作為列表的一部分);儲存常量的值(對布林開關true/false有特殊處理)。預設動作是儲存引數值。支援type(指定儲存型別)和dest(指定儲存變數)等引數。
然後使用函式parse_args()進行引數解析,這個函式的輸入預設是sys.argv[1:],也可以使用其他字串列表。選項使用GNU/POSIX語法處理,可以混合選項和引數值。parse_args的返回值是一個包含命令引數的Namespace。所有引數以屬性的形式存在,比如args.myoption。
下面是一個簡單的示例:argparse_short.py
import argparse parser = argparse.ArgumentParser(description='Short sample app') parser.add_argument('-a', action="store_true", default=False) parser.add_argument('-b', action="store", dest="b") parser.add_argument('-c', action="store", dest="c", type=int) print(parser.parse_args(['-a', '-bval', '-c', '3']))
執行結果:
$ python3 argparse_short.py Namespace(a=True, b='val', c=3)
長引數argparse_long.py
import argparse parser = argparse.ArgumentParser( description='Example with long option names', ) parser.add_argument('--noarg', action="store_true", default=False) parser.add_argument('--witharg', action="store", dest="witharg") parser.add_argument('--witharg2', action="store", dest="witharg2", type=int) print( parser.parse_args( ['--noarg', '--witharg', 'val', '--witharg2=3'] ) )
執行結果
$ python3 argparse_long.py Namespace(noarg=True, witharg='val', witharg2=3)
混合可選和必選引數:argparse_arguments.py
import argparse parser = argparse.ArgumentParser( description='Example with nonoptional arguments', ) parser.add_argument('count', action="store", type=int) parser.add_argument('units', action="store") print(parser.parse_args())
執行結果
$ python3 argparse_arguments.py 3 inches Namespace(count=3, units='inches') $ python3 argparse_arguments.py some inches usage: argparse_arguments.py [-h] count units argparse_arguments.py: error: argument count: invalid int value: 'some' $ python3 argparse_arguments.py usage: argparse_arguments.py [-h] count units argparse_arguments.py: error: the following arguments are required: count, units
引數action有:
store:預設action模式,儲存值到指定變數。
store_const:儲存值在引數的const部分指定,多用於實現非布林的命令列flag。
store_true / store_false:布林開關。可以2個引數對應一個變數。
append:儲存值到列表,該引數可以重複使用。
append_const:儲存值到列表,儲存值在引數的const部分指定。
version 輸出版本資訊然後退出。
下面是各種action的示例:argparse_action.py
import argparse parser = argparse.ArgumentParser() parser.add_argument('-s', action='store', dest='simple_value', help='Store a simple value') parser.add_argument('-c', action='store_const', dest='constant_value', const='value-to-store', help='Store a constant value') parser.add_argument('-t', action='store_true', default=False, dest='boolean_t', help='Set a switch to true') parser.add_argument('-f', action='store_false', default=True, dest='boolean_f', help='Set a switch to false') parser.add_argument('-a', action='append', dest='collection', default=[], help='Add repeated values to a list') parser.add_argument('-A', action='append_const', dest='const_collection', const='value-1-to-append', default=[], help='Add different values to list') parser.add_argument('-B', action='append_const', dest='const_collection', const='value-2-to-append', help='Add different values to list') parser.add_argument('--version', action='version', version='%(prog)s 1.0') results = parser.parse_args() print('simple_value= {!r}'.format(results.simple_value)) print('constant_value= {!r}'.format(results.constant_value)) print('boolean_t= {!r}'.format(results.boolean_t)) print('boolean_f= {!r}'.format(results.boolean_f)) print('collection= {!r}'.format(results.collection)) print('const_collection = {!r}'.format(results.const_collection))
執行結果如下,注意'simple_value'等被自動化轉化為大寫
$ python3 argparse_action.py -h usage: argparse_action.py [-h] [-s SIMPLE_VALUE] [-c] [-t] [-f] [-a COLLECTION] [-A] [-B] [--version] optional arguments: -h, --helpshow this help message and exit -s SIMPLE_VALUEStore a simple value -cStore a constant value -tSet a switch to true -fSet a switch to false -a COLLECTIONAdd repeated values to a list -AAdd different values to list -BAdd different values to list --versionshow program's version number and exit $ python3 argparse_action.py -s value simple_value= 'value' constant_value= None boolean_t= False boolean_f= True collection= [] const_collection = [] $ python3 argparse_action.py -c simple_value= None constant_value= 'value-to-store' boolean_t= False boolean_f= True collection= [] const_collection = [] $ python3 argparse_action.py -t simple_value= None constant_value= None boolean_t= True boolean_f= True collection= [] const_collection = [] $ python3 argparse_action.py -f simple_value= None constant_value= None boolean_t= False boolean_f= False collection= [] const_collection = [] $ python3 argparse_action.py -a one -a two -a three simple_value= None constant_value= None boolean_t= False boolean_f= True collection= ['one', 'two', 'three'] const_collection = [] $ python3 argparse_action.py -B -A simple_value= None constant_value= None boolean_t= False boolean_f= True collection= [] const_collection = ['value-2-to-append', 'value-1-to-append'] $ python3 argparse_action.py --version argparse_action.py 1.0
參考資料
- 討論 釘釘群21745728 qq群144081101 567351477
- ofollow,noindex">本文涉及的python測試開發庫 謝謝點贊!
- 本文相關海量書籍下載
- python工具書籍下載-持續更新
- 本文最新版本地址
可選字首
ArgumentParser函式中的選項prefix_chars可以指定字首。預設使用UNIX風格,命令列使用‘-’作為字首。可以使用windows的’/’或者其他符號。
argparse_prefix_chars.py
import argparse parser = argparse.ArgumentParser( description='Change the option prefix characters', prefix_chars='-+/', ) parser.add_argument('-a', action="store_false", default=None, help='Turn A off', ) parser.add_argument('+a', action="store_true", default=None, help='Turn A on', ) parser.add_argument('//noarg', '++noarg', action="store_true", default=False) print(parser.parse_args())
執行結果
$ python3 argparse_prefix_chars.py -h usage: argparse_prefix_chars.py [-h] [-a] [+a] [//noarg] Change the option prefix characters optional arguments: -h, --helpshow this help message and exit -aTurn A off +aTurn A on //noarg, ++noarg $ python3 argparse_prefix_chars.py +a Namespace(a=True, noarg=False) $ python3 argparse_prefix_chars.py -a Namespace(a=False, noarg=False) $ python3 argparse_prefix_chars.py //noarg Namespace(a=None, noarg=True) $ python3 argparse_prefix_chars.py ++noarg Namespace(a=None, noarg=True) $ python3 argparse_prefix_chars.py --noarg usage: argparse_prefix_chars.py [-h] [-a] [+a] [//noarg] argparse_prefix_chars.py: error: unrecognized arguments: --noarg
處理配置檔案中的引數
argparse_with_shlex.py
import argparse from configparser import ConfigParser import shlex parser = argparse.ArgumentParser(description='Short sample app') parser.add_argument('-a', action="store_true", default=False) parser.add_argument('-b', action="store", dest="b") parser.add_argument('-c', action="store", dest="c", type=int) config = ConfigParser() config.read('argparse_with_shlex.ini') config_value = config.get('cli', 'options') print('Config:', config_value) argument_list = shlex.split(config_value) print('Arg List:', argument_list) print('Results :', parser.parse_args(argument_list))
其中argparse_with_shlex.ini檔案的內容如下:
[cli] options = -a -b 2
執行結果
$ python3 argparse_with_shlex.py Config: -a -b 2 Arg List: ['-a', '-b', '2'] Results : Namespace(a=True, b='2', c=None)
上面例子使用了ConfigParser來讀取配置,再用shlex來切割引數。也可以通過fromfile_prefix_chars 告知argparse輸入引數為檔案。
argparse_fromfile_prefix_chars.py
import argparse import shlex parser = argparse.ArgumentParser(description='Short sample app', fromfile_prefix_chars='@', ) parser.add_argument('-a', action="store_true", default=False) parser.add_argument('-b', action="store", dest="b") parser.add_argument('-c', action="store", dest="c", type=int) print(parser.parse_args(['@argparse_fromfile_prefix_chars.txt']))
argparse_fromfile_prefix_chars.txt
-a -b 2
執行結果
$ python3 argparse_fromfile_prefix_chars.py Namespace(a=True, b='2', c=None)
幫助
- 自動生成
Argparse會自動生成的幫助和版本資訊。ArgumentParser的add_help引數控制幫助的生成,預設是開啟。
argparse_with_help.py
import argparse parser = argparse.ArgumentParser(add_help=True) parser.add_argument('-a', action="store_true", default=False) parser.add_argument('-b', action="store", dest="b") parser.add_argument('-c', action="store", dest="c", type=int) print(parser.parse_args())
下例就關閉幫助:
argparse_without_help.py
import argparse parser = argparse.ArgumentParser(add_help=False) parser.add_argument('-a', action="store_true", default=False) parser.add_argument('-b', action="store", dest="b") parser.add_argument('-c', action="store", dest="c", type=int) print(parser.parse_args())
執行結果
$ python argparse_with_help.py -h usage: argparse_with_help.py [-h] [-a] [-b B] [-c C] optional arguments: -h, --help show this help message and exit -a -b B -c C $ python argparse_without_help.py -h usage: argparse_without_help.py [-a] [-b B] [-c C] argparse_without_help.py: error: unrecognized arguments: -h
- 自定義幫助
argparse_custom_help.py
import argparse parser = argparse.ArgumentParser(add_help=True) parser.add_argument('-a', action="store_true", default=False) parser.add_argument('-b', action="store", dest="b") parser.add_argument('-c', action="store", dest="c", type=int) print('print_usage output:') parser.print_usage() print() print('print_help output:') parser.print_help()
執行結果
$ python3 argparse_custom_help.py print_usage output: usage: argparse_custom_help.py [-h] [-a] [-b B] [-c C] print_help output: usage: argparse_custom_help.py [-h] [-a] [-b B] [-c C] optional arguments: -h, --helpshow this help message and exit -a -b B -c C
argparse_raw_description_help_formatter.py
import argparse parser = argparse.ArgumentParser( add_help=True, formatter_class=argparse.RawDescriptionHelpFormatter, description=""" description not wrapped""", epilog=""" epilog not wrapped""", ) parser.add_argument( '-a', action="store_true", help="""argument help is wrapped """, ) parser.print_help()
執行結果
$ python3 argparse_raw_description_help_formatter.py usage: argparse_raw_description_help_formatter.py [-h] [-a] description not wrapped optional arguments: -h, --helpshow this help message and exit -aargument help is wrapped epilog not wrapped
argparse_raw_text_help_formatter.py
import argparse parser = argparse.ArgumentParser( add_help=True, formatter_class=argparse.RawTextHelpFormatter, description=""" description not wrapped""", epilog=""" epilog not wrapped""", ) parser.add_argument( '-a', action="store_true", help="""argument help is not wrapped """, ) parser.print_help()
執行結果
$ python3 argparse_raw_text_help_formatter.py usage: argparse_raw_text_help_formatter.py [-h] [-a] description not wrapped optional arguments: -h, --helpshow this help message and exit -aargument help is not wrapped epilog not wrapped
argparse_metavar_type_help_formatter.py
import argparse parser = argparse.ArgumentParser( add_help=True, formatter_class=argparse.MetavarTypeHelpFormatter, ) parser.add_argument('-i', type=int, dest='notshown1') parser.add_argument('-f', type=float, dest='notshown2') parser.print_help()
執行結果
$ python3 argparse_metavar_type_help_formatter.py usage: argparse_metavar_type_help_formatter.py [-h] [-i int] [-f float] optional arguments: -h, --helpshow this help message and exit -i int -f float
組織解析器
公共解析器:通過父子類來實現。
見argparse_parent_base.py:
import argparse parser = argparse.ArgumentParser(add_help=False) parser.add_argument('--user', action="store") parser.add_argument('--password', action="store")
argparse_uses_parent.py
import argparse import argparse_parent_base parser = argparse.ArgumentParser( parents=[argparse_parent_base.parser], ) parser.add_argument('--local-arg', action="store_true", default=False) print(parser.parse_args())
注意:父類關閉了help。子類卻預設開啟了help。執行結果:
$ python3 argparse_uses_parent.py -h usage: argparse_uses_parent.py [-h] [--user USER] [--password PASSWORD] [--local-arg] optional arguments: -h, --helpshow this help message and exit --user USER --password PASSWORD --local-arg
引數衝突
argparse_conflict_handler_resolve.py
import argparse parser = argparse.ArgumentParser(conflict_handler='resolve') parser.add_argument('-a', action="store") parser.add_argument('-b', action="store", help='Short alone') parser.add_argument('--long-b', '-b', action="store", help='Long and short together') print(parser.parse_args(['-h']))
執行結果
$ python3 argparse_conflict_handler_resolve.py usage: argparse_conflict_handler_resolve.py [-h] [-a A] [--long-b LONG_B] optional arguments: -h, --helpshow this help message and exit -a A --long-b LONG_B, -b LONG_B Long and short together
argparse_conflict_handler_resolve2.py、
import argparse parser = argparse.ArgumentParser(conflict_handler='resolve') parser.add_argument('-a', action="store") parser.add_argument('--long-b', '-b', action="store", help='Long and short together') parser.add_argument('-b', action="store", help='Short alone') print(parser.parse_args(['-h']))
執行結果
$ python3 argparse_conflict_handler_resolve2.py usage: argparse_conflict_handler_resolve2.py [-h] [-a A] [--long-b LONG_B] [-b B] optional arguments: -h, --helpshow this help message and exit -a A --long-b LONG_BLong and short together -b BShort alone
引數分組
預設有可選引數和必選引數組。
argparse_default_grouping.py
import argparse parser = argparse.ArgumentParser(description='Short sample app') parser.add_argument('--optional', action="store_true", default=False) parser.add_argument('positional', action="store") print(parser.parse_args())
執行結果
$ python3 argparse_default_grouping.py -h usage: argparse_default_grouping.py [-h] [--optional] positional Short sample app positional arguments: positional optional arguments: -h, --helpshow this help message and exit --optional
前面的使用者名稱和密碼就可以分組:
argparse_parent_with_group.py
import argparse parser = argparse.ArgumentParser(add_help=False) group = parser.add_argument_group('authentication') group.add_argument('--user', action="store") group.add_argument('--password', action="store")
argparse_uses_parent_with_group.py
import argparse import argparse_parent_with_group parser = argparse.ArgumentParser( parents=[argparse_parent_with_group.parser], ) parser.add_argument('--local-arg', action="store_true", default=False) print(parser.parse_args())
執行結果
$ python3 argparse_uses_parent_with_group.py -h usage: argparse_uses_parent_with_group.py [-h] [--user USER] [--password PASSWORD] [--local-arg] optional arguments: -h, --helpshow this help message and exit --local-arg authentication: --user USER --password PASSWORD
互斥選項
使用add_mutually_exclusive_group()可以新增互斥選項:
argparse_mutually_exclusive.py
import argparse parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group() group.add_argument('-a', action='store_true') group.add_argument('-b', action='store_true') print(parser.parse_args())
執行結果
$ python3 argparse_mutually_exclusive.py -h usage: argparse_mutually_exclusive.py [-h] [-a | -b] optional arguments: -h, --helpshow this help message and exit -a -b $ python3 argparse_mutually_exclusive.py -a Namespace(a=True, b=False) $ python3 argparse_mutually_exclusive.py -b Namespace(a=False, b=True) $ python3 argparse_mutually_exclusive.py -a -b usage: argparse_mutually_exclusive.py [-h] [-a | -b] argparse_mutually_exclusive.py: error: argument -b: not allowed with argument -a
巢狀解析
argparse_subparsers.py
import argparse parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(help='commands') # A list command list_parser = subparsers.add_parser( 'list', help='List contents') list_parser.add_argument( 'dirname', action='store', help='Directory to list') # A create command create_parser = subparsers.add_parser( 'create', help='Create a directory') create_parser.add_argument( 'dirname', action='store', help='New directory to create') create_parser.add_argument( '--read-only', default=False, action='store_true', help='Set permissions to prevent writing to the directory', ) # A delete command delete_parser = subparsers.add_parser( 'delete', help='Remove a directory') delete_parser.add_argument( 'dirname', action='store', help='The directory to remove') delete_parser.add_argument( '--recursive', '-r', default=False, action='store_true', help='Remove the contents of the directory, too', ) print(parser.parse_args())
執行結果
$ python3 argparse_subparsers.py -h usage: argparse_subparsers.py [-h] {list,create,delete} ... positional arguments: {list,create,delete}commands listList contents createCreate a directory deleteRemove a directory optional arguments: -h, --helpshow this help message and exit $ python3 argparse_subparsers.py create -h usage: argparse_subparsers.py create [-h] [--read-only] dirname positional arguments: dirnameNew directory to create optional arguments: -h, --helpshow this help message and exit --read-onlySet permissions to prevent writing to the directo ry $ python3 argparse_subparsers.py delete -r foo Namespace(dirname='foo', recursive=True)
高階引數處理
可變引數:數字N代表N的引數,?0或者1個引數。*0或者多個引數。+1或者多個引數。
argparse_nargs.py
import argparse parser = argparse.ArgumentParser() parser.add_argument('--three', nargs=3) parser.add_argument('--optional', nargs='?') parser.add_argument('--all', nargs='*', dest='all') parser.add_argument('--one-or-more', nargs='+') print(parser.parse_args())
執行結果
$ python3 argparse_nargs.py -h usage: argparse_nargs.py [-h] [--three THREE THREE THREE] [--optional [OPTIONAL]] [--all [ALL [ALL ...]]] [--one-or-more ONE_OR_MORE [ONE_OR_MORE ...]] optional arguments: -h, --helpshow this help message and exit --three THREE THREE THREE --optional [OPTIONAL] --all [ALL [ALL ...]] --one-or-more ONE_OR_MORE [ONE_OR_MORE ...] $ python3 argparse_nargs.py Namespace(all=None, one_or_more=None, optional=None, three=None) $ python3 argparse_nargs.py --three usage: argparse_nargs.py [-h] [--three THREE THREE THREE] [--optional [OPTIONAL]] [--all [ALL [ALL ...]]] [--one-or-more ONE_OR_MORE [ONE_OR_MORE ...]] argparse_nargs.py: error: argument --three: expected 3 argument(s) $ python3 argparse_nargs.py --three a b c Namespace(all=None, one_or_more=None, optional=None, three=['a', 'b', 'c']) $ python3 argparse_nargs.py --optional Namespace(all=None, one_or_more=None, optional=None, three=None) $ python3 argparse_nargs.py --optional with_value Namespace(all=None, one_or_more=None, optional='with_value', three=None) $ python3 argparse_nargs.py --all with multiple values Namespace(all=['with', 'multiple', 'values'], one_or_more=None, optional=None, three=None) $ python3 argparse_nargs.py --one-or-more with_value Namespace(all=None, one_or_more=['with_value'], optional=None, three=None) $ python3 argparse_nargs.py --one-or-more with multiple values Namespace(all=None, one_or_more=['with', 'multiple', 'values'], optional=None, three=None) $ python3 argparse_nargs.py --one-or-more usage: argparse_nargs.py [-h] [--three THREE THREE THREE] [--optional [OPTIONAL]] [--all [ALL [ALL ...]]] [--one-or-more ONE_OR_MORE [ONE_OR_MORE ...]] argparse_nargs.py: error: argument --one-or-more: expected at least one argument
引數型別
argparse_type.py
import argparse parser = argparse.ArgumentParser() parser.add_argument('-i', type=int) parser.add_argument('-f', type=float) parser.add_argument('--file', type=open) try: print(parser.parse_args()) except IOError as msg: parser.error(str(msg))
執行結果
$ python3 argparse_type.py -i 1 Namespace(f=None, file=None, i=1) $ python3 argparse_type.py -f 3.14 Namespace(f=3.14, file=None, i=None) $ python3 argparse_type.py --file argparse_type.py Namespace(f=None, file=<_io.TextIOWrapper name='argparse_type.py' mode='r' encoding='UTF-8'>, i=None) $ python3 argparse_type.py -i a usage: argparse_type.py [-h] [-i I] [-f F] [--file FILE] argparse_type.py: error: argument -i: invalid int value: 'a' $ python3 argparse_type.py -f 3.14.15 usage: argparse_type.py [-h] [-i I] [-f F] [--file FILE] argparse_type.py: error: argument -f: invalid float value: '3.14.15' $ python3 argparse_type.py --file does_not_exist.txt usage: argparse_type.py [-h] [-i I] [-f F] [--file FILE] argparse_type.py: error: [Errno 2] No such file or directory: 'does_not_exist.txt'
Choices可以指定引數的選項:
argparse_choices.py
import argparse parser = argparse.ArgumentParser() parser.add_argument( '--mode', choices=('read-only', 'read-write'), ) print(parser.parse_args())
執行結果
$ python3 argparse_choices.py -h usage: argparse_choices.py [-h] [--mode {read-only,read-write}] optional arguments: -h, --helpshow this help message and exit --mode {read-only,read-write} $ python3 argparse_choices.py --mode read-only Namespace(mode='read-only') $ python3 argparse_choices.py --mode invalid usage: argparse_choices.py [-h] [--mode {read-only,read-write}] argparse_choices.py: error: argument --mode: invalid choice: 'invalid' (choose from 'read-only', 'read-write')
檔案引數
argparse_FileType.py
import argparse parser = argparse.ArgumentParser() parser.add_argument('-i', metavar='in-file', type=argparse.FileType('rt')) parser.add_argument('-o', metavar='out-file', type=argparse.FileType('wt')) try: results = parser.parse_args() print('Input file:', results.i) print('Output file:', results.o) except IOError as msg: parser.error(str(msg))
執行結果
$ python3 argparse_FileType.py -h usage: argparse_FileType.py [-h] [-i in-file] [-o out-file] optional arguments: -h, --helpshow this help message and exit -i in-file -o out-file $ python3 argparse_FileType.py -i argparse_FileType.py -o tmp_\ file.txt Input file: <_io.TextIOWrapper name='argparse_FileType.py' mode='rt' encoding='UTF-8'> Output file: <_io.TextIOWrapper name='tmp_file.txt' mode='wt' encoding='UTF-8'> $ python3 argparse_FileType.py -i no_such_file.txt usage: argparse_FileType.py [-h] [-i in-file] [-o out-file] argparse_FileType.py: error: argument -i: can't open 'no_such_file.txt': [Errno 2] No such file or directory: 'no_such_file.txt'
自定義action
自定義action是argparse.Action的子類可以處理add_argument中的引數定義相關的引數,並返回一個可呼叫物件。建構函式會處理引數定義,僅僅需要處理call 函式。call 函式中parser代表直譯器,namespace用於返回解釋結果,value為要處理的引數,option_string用於觸發action(對可選引數,永遠是None。
argparse_custom_action.py
import argparse class CustomAction(argparse.Action): def __init__(self, option_strings, dest, nargs=None, const=None, default=None, type=None, choices=None, required=False, help=None, metavar=None): argparse.Action.__init__(self, option_strings=option_strings, dest=dest, nargs=nargs, const=const, default=default, type=type, choices=choices, required=required, help=help, metavar=metavar, ) print('Initializing CustomAction') for name, value in sorted(locals().items()): if name == 'self' or value is None: continue print('{} = {!r}'.format(name, value)) print() return def __call__(self, parser, namespace, values, option_string=None): print('Processing CustomAction for {}'.format(self.dest)) print('parser = {}'.format(id(parser))) print('values = {!r}'.format(values)) print('option_string = {!r}'.format(option_string)) # Do some arbitrary processing of the input values if isinstance(values, list): values = [v.upper() for v in values] else: values = values.upper() # Save the results in the namespace using the destination # variable given to our constructor. setattr(namespace, self.dest, values) print() parser = argparse.ArgumentParser() parser.add_argument('-a', action=CustomAction) parser.add_argument('-m', nargs='*', action=CustomAction) results = parser.parse_args(['-a', 'value', '-m', 'multivalue', 'second']) print(results)
執行結果
$ python3 argparse_custom_action.py Initializing CustomAction dest = 'a' option_strings = ['-a'] required = False Initializing CustomAction dest = 'm' nargs = '*' option_strings = ['-m'] required = False Processing CustomAction for a parser = 4315836992 values = 'value' option_string = '-a' Processing CustomAction for m parser = 4315836992 values = ['multivalue', 'second'] option_string = '-m' Namespace(a='VALUE', m=['MULTIVALUE', 'SECOND'])