В примере ниже продемонстрировано использование субкоманд (или “подкоманд“) с использованием модуля argparse.
К примеру, в предыдущем проекте скрипт управления приложением имел около 20-ти различных опцией (был написан на BASH с использованием getopts()), при том что букв в английском алфавите – 26.
В новом проекте – имеется аналогичный скрипт, но на Python.
Приложение состоит из нескольких частей, и для каждой хочется иметь возможность вызывать опции --deploy
или --makeconf
.
Реализуется такое с помощью метода add_subparsers:
import argparse ... def getopts(): """Create list from called options""" parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(help='Application part to act with') # unity options # parser.add_argument('-r', '--refresh', nargs='?', const='dev', help=('Refresh modules DLLs and xml files')) # parser.add_argument('-r', '--refresh', choices=['dev', 'ci'], help=('Refresh modules DLLs and xml files')) ### добавляем новый аргумент `unity`, который будет играть роль "пространства имён" для опций # таким образом - мы можем использовать например --deploy или -d в разных аргументах # при этом с помощью set_defaults(func=handler_unity) мы определяем, какая функция будет заниматься ### обработкой аргументов для этого "пространства имён" parser_unity = subparsers.add_parser('unity', help='Unity application') parser_unity.set_defaults(func=handler_unity) parser_unity.add_argument('-r', '--refresh', action='store_true', dest='unity_refresh', help='Copy necessarry DLLs to MainApplication\Assets\PreparedPlugins and NGUIProject\Assets\PreparedPlugins') parser_unity.add_argument('-t', '--tagcheck', action='store_true', dest='unity_tagcheck', help='Check tags in .csproj files') parser_unity.add_argument('-b', '--buildtype', nargs='?', choices=['dev', 'ci'], default='dev', dest='unity_buildtype', help='Select unity - for developer or CI server') parser_unity.add_argument('-c', '--confgen', action='store_true', dest='unity_confgen', help='Generate config.xml and XMLs for each module with TAG = 'CLOUD'') parser_unity.add_argument('-u', '--uuidgen', action='store', dest='unity_uuidgen', help='Generate UUIDs for each module in Plugins.sln. Must be called with 'config_name' as first argument and optionally - with `-b ci` option') parser_unity.add_argument('-l', '--configlist', action='store_true', dest='unity_configlist', help='Display configuration names in uuids.ini') parser_unity.add_argument('-d', '--deploy', action='store_true', dest='unity_deploy', help='Deploy Unity project to appropriate URL') # Cloudlibrary options parser_rds = subparsers.add_parser('clc', help='Cloudlibrary options') parser_rds.set_defaults(func=handler_clc) parser_rds.add_argument('-d', '--deploy', dest='clc_deploy', action='store_true', help='Update RDSmanager from repository') # for Clc lib external usage parser_rds.add_argument('-u', '--user', action='store', dest='clc_user', help='Username for authorization') parser_rds.add_argument('-x', '--password', action='store', dest='clc_password', help='Password for authorization') parser_rds.add_argument('-f', '--file', action='store', dest='clc_file', help='Specify local file to save to/upload from') # Cloudlibrary requests types parser_rds.add_argument('-g', '--get', action='store', dest='clc_get', help='Request type GET') parser_rds.add_argument('-p', '--put', action='store', dest='clc_put', help='Request type PUT') parser_rds.add_argument('--delete', action='store', dest='clc_del', help='Request type DELETE') # RDSmanager own options parser_rds = subparsers.add_parser('rds', help='RDSmanager options') parser_rds.set_defaults(func=handler_rds) parser_rds.add_argument('-s', '--selfupgrade', dest='rds_selfupgrade', action='store_true', help='Update RDSmanager from repository') parser_rds.add_argument('-T', '--test', action='store_true', dest='rds_test', help='Temporary test option') if len(sys.argv) <= 1: parser.print_help() sys.exit(1) else: res = parser.parse_args() res.func(res) def handler_unity(action_list): """Check Unity namespace options""" if action_list.unity_tagcheck: logger.logger.info('Running tagcheck') from lib.unity import tag_checker tag_checker.main(logger) if action_list.unity_refresh: logger.logger.info('Running refresh modules') from lib.unity import refresh refresh.refresh(logger) if action_list.unity_confgen: logger.logger.info('Running confgen') from lib.unity import confgen confgen.main(logger, RDS_BASEDIR, action_list.unity_buildtype) if action_list.unity_uuidgen: logger.logger.info('Running UUID generator with %s' % action_list.unity_uuidgen) from lib.unity import uuidgen uuidgen.uuidgen(logger, RDS_BASEDIR, action_list.unity_uuidgen, action_list.unity_buildtype) if action_list.unity_configlist: logger.logger.info('Running configlist') from lib.unity import confgen confgen.configlist(logger, RDS_BASEDIR) if action_list.unity_deploy: logger.logger.info('Running DEPLOY buildtype = %s' % action_list.unity_buildtype) from lib.unity import deploy deploy.main(logger, CLC_USER, CLC_PASSWORD, RDS_BASEDIR, action_list.unity_buildtype) def handler_clc(action_list): """Check Cloudlibrary namespace options""" if action_list.clc_deploy: from lib.clc import deploy deploy.deploy(logger, RDS_BASEDIR) if action_list.clc_get: from lib.external.rds_clc import RdsClc if not action_list.clc_user and not action_list.clc_password: logger.logger.info('Nether CLC_USER not CLC_PASSWORD found, using default values') action_list.clc_user = CLC_USER action_list.clc_password = CLC_PASSWORD req = RdsClc(action_list.clc_user, action_list.clc_password) req.cloud_get(action_list.clc_get, action_list.clc_file) if action_list.clc_put: from lib.external.rds_clc import RdsClc if not action_list.clc_user and not action_list.clc_password: logger.logger.info('Nether CLC_USER not CLC_PASSWORD found, using default values') action_list.clc_user = CLC_USER action_list.clc_password = CLC_PASSWORD req = RdsClc(action_list.clc_user, action_list.clc_password) req.cloud_put(action_list.clc_put, action_list.clc_file) if action_list.clc_del: from lib.external.rds_clc import RdsClc if not action_list.clc_user and not action_list.clc_password: logger.logger.info('Nether CLC_USER not CLC_PASSWORD found, using default values') action_list.clc_user = CLC_USER action_list.clc_password = CLC_PASSWORD req = RdsClc(action_list.clc_user, action_list.clc_password) req.cloud_delete(action_list.clc_del) def handler_rds(action_list): """Check RDS namespace options""" if action_list.rds_test: logger.logger.info('Running TEST option') from lib.external import testing5 testing5.test(logger) if action_list.rds_selfupgrade: logger.logger.info('Running self-upgrade') from lib.service import manager manager.selfupgrade(logger, RDS_BASEDIR) if __name__ == '__main__': logger = Logger(RDS_BASEDIR) logger.logger('RDSmanager') logger.logger.info('RDSmanager started at %s' % (time.strftime('%d, %b %Y at %H:%M:%S'))) getopts()
Помощь теперь выглядит так:
d:RDSrdsmanager>RDSmanager.py rds -h RDSmanager started at 25, Jun 2015 at 18:26:46 usage: RDSmanager.py rds [-h] [-s] [-T] optional arguments: -h, --help show this help message and exit -s, --selfupgrade Update RDSmanager from repository -T, --test Temporary test option
d:RDSrdsmanager>RDSmanager.py clc -h RDSmanager started at 25, Jun 2015 at 18:37:04 usage: RDSmanager.py clc [-h] [-d] [-u CLC_USER] [-x CLC_PASSWORD] [-f CLC_FILE] [-g CLC_GET] [-p CLC_PUT] [--delete CLC_DEL] optional arguments: -h, --help show this help message and exit -d, --deploy Update RDSmanager from repository -u CLC_USER, --user CLC_USER Username for authorization -x CLC_PASSWORD, --password CLC_PASSWORD Password for authorization -f CLC_FILE, --file CLC_FILE Specify local file to save to/upload from -g CLC_GET, --get CLC_GET Request type GET -p CLC_PUT, --put CLC_PUT Request type PUT --delete CLC_DEL Request type DELETE
И так далее.