1、getopt 模块
此模块可协助脚本解析 sys.argv 中的命令行参数。 它支持与 Unix getopt() 函数相同的惯例(包括形式如 '-' 与 '--' 的参数的特殊含义)。 也能通过可选的第三个参数来使用与 GNU 软件所支持形式相类似的长选项。
1)getopt.getopt(args, shortopts, longopts=[])
方法作用是用于解析命令行选项与形参列表, args 为要解析的参数列表,不包含最开头的对正在运行的程序的引用。 通常这意味着 sys.argv[1:]。 shortopts 为脚本所要识别的字母选项,包含要求后缀一个冒号 (':';即与 Unix getopt() 所用的格式相同) 的选项。另外,与 GNU getopt() 不同,在非选项参数之后,所有后续参数都会被视为非选项。 这类似于非 GNU Unix 系统的运作方式。
import getopt import sys # 命令行参数列表 argv = sys.argv[1:] # 定义短选项字符串 short_options = "ho:v" # 定义长选项字符串 long_options = ["help", "output=", "verbose"] # 使用 getopt 解析命令行参数 try: opts, args = getopt.getopt(argv, short_options, long_options) except getopt.GetoptError: print("Usage: example.py -o <outputfile> -v") sys.exit(2) output_file = None verbose = False # 处理解析结果 for opt, arg in opts: if opt in ("-h", "--help"): print("Usage: example.py -o <outputfile> -v") sys.exit() elif opt in ("-o", "--output"): output_file = arg elif opt in ("-v", "--verbose"): verbose = True print("Output file:", output_file) print("Verbose mode:", verbose) print("Remaining args:", args)
注意:getopt 模块是一个命令行选项解析器,其 API 设计会让 C getopt() 函数的用户感到熟悉。 不熟悉 C getopt() 函数或者希望写更少代码并获得更完善帮助和错误消息的用户应当考虑改用 argparse 模块。
2)getopt.gnu_getopt(args, shortopts, longopts=[])
此函数与 getopt() 类似,区别在于它默认使用 GNU 风格的扫描模式。 意味着选项和非选项参数可能会混在一起。 getopt() 函数将在遇到非选项参数时立即停止处理选项。
如果选项字符串的第一个字符为 '+',或者如果设置了环境变量 POSIXLY_CORRECT,则选项处理会在遇到非选项参数时立即停止。
import getopt import sys # 命令行参数列表 args = ["--input", "inputfile.txt", "--output", "outputfile.txt", "--verbose", "--help"] # 定义短选项字符串 shortopts = "hi:o:v" # 定义长选项列表 longopts = ["help", "input=", "output=", "verbose"] # 使用 getopt.gnu_getopt 解析命令行参数 opts, args = getopt.gnu_getopt(args, shortopts, longopts) input_file = None output_file = None verbose = False # 处理解析结果 for opt, arg in opts: if opt in ("-h", "--help"): print("Usage: example.py -i <inputfile> -o <outputfile> -v") sys.exit() elif opt in ("-i", "--input"): input_file = arg elif opt in ("-o", "--output"): output_file = arg elif opt in ("-v", "--verbose"): verbose = True print("Input file:", input_file) print("Output file:", output_file)
3)exception getopt.GetoptError
当参数列表中出现不可识别的选项或者当一个需要参数的选项未带参数时将引发此异常。 此异常的参数是一个指明错误原因的字符串。 对于长选项,将一个参数传给不需要参数的选项也将导致引发此异常。 msg 和 opt 属性会给出错误消息和关联的选项;如果没有关联到异常的特定选项,则 opt 将为空字符串。
exception getopt.error
是GetoptError
的别名;用于向后兼容。
参考文档:https://docs.python.org/zh-cn/3/library/getopt.html
2、 argparse 模块
可以使用更少的代码并附带更详细的帮助与错误消息生成等价的命令行接口,如下,
import argparse if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('-o', '--output') parser.add_argument('-v', dest='verbose', action='store_true') args = parser.parse_args() print(args)
参考文档:https://docs.python.org/zh-cn/3/library/argparse.html#module-argparse
3、getopt 模块使用示例
getopt 模块使用完整示例,包括exception getopt.GetoptError的处理,日志的输出,参数获取判断,如下,
import getopt import os import platform import sys TERM = os.getenv('TERM', '') IS_ANSI_TERMINAL = TERM in ( 'eterm-color', 'linux', 'screen', 'vt100', ) or TERM.startswith('xterm') RESET = 0 BOLD = 1 UNDERLINE = 4 NEGATIVE = 7 NO_BOLD = 21 NO_UNDERLINE = 24 POSITIVE = 27 BLACK = 30 RED = 31 GREEN = 32 YELLOW = 33 BLUE = 34 MAGENTA = 35 CYAN = 36 LIGHT_GRAY = 37 DEFAULT = 39 BLACK_BACKGROUND = 40 RED_BACKGROUND = 41 GREEN_BACKGROUND = 42 YELLOW_BACKGROUND = 43 BLUE_BACKGROUND = 44 MAGENTA_BACKGROUND = 45 CYAN_BACKGROUND = 46 LIGHT_GRAY_BACKGROUND = 47 DEFAULT_BACKGROUND = 49 DARK_GRAY = 90 # xterm LIGHT_RED = 91 # xterm LIGHT_GREEN = 92 # xterm LIGHT_YELLOW = 93 # xterm LIGHT_BLUE = 94 # xterm LIGHT_MAGENTA = 95 # xterm LIGHT_CYAN = 96 # xterm WHITE = 97 # xterm DARK_GRAY_BACKGROUND = 100 # xterm LIGHT_RED_BACKGROUND = 101 # xterm LIGHT_GREEN_BACKGROUND = 102 # xterm LIGHT_YELLOW_BACKGROUND = 103 # xterm LIGHT_BLUE_BACKGROUND = 104 # xterm LIGHT_MAGENTA_BACKGROUND = 105 # xterm LIGHT_CYAN_BACKGROUND = 106 # xterm WHITE_BACKGROUND = 107 # xterm def sprint(text, *colors): """Format text with color or other effects into ANSI escaped string.""" return "\33[{}m{content}\33[{}m".format(";".join([str(color) for color in colors]), RESET, content=text) if IS_ANSI_TERMINAL and colors else text def println(text, *colors): """Print text to standard output.""" sys.stdout.write(sprint(text, *colors) + "\n") def print_err(text, *colors): """Print text to standard error.""" sys.stderr.write(sprint(text, *colors) + "\n") def wtf(message, exit_code=1): """What a Terrible Failure!""" print_log(message, RED, BOLD) if exit_code is not None: sys.exit(exit_code) def print_log(text, *colors): """Print a log message to standard error.""" sys.stderr.write(sprint("{}: {}".format(script_name, text), *colors) + "\n") script_name="cjavapy" _options = [ 'help', 'version', 'gui', 'force', 'playlists', ] _short_options = 'hVgfl' _help = """Usage: {} [OPTION]... [URL]... TODO """.format(script_name) def main(**kwargs): """Main entry point. dev """ # Get (branch, commit) if running from a git repo. head = 'repo_path' # Get options and arguments. try: opts, args = getopt.getopt(sys.argv[1:], _short_options, _options) except getopt.GetoptError as e: wtf(""" [Fatal] {}. Try '{} --help' for more options.""".format(e, script_name)) if not opts and not args: # Display help. print(_help) # Enter GUI mode. #from .gui import gui_main #gui_main() else: conf = {} for opt, arg in opts: if opt in ('-h', '--help'): # Display help. print(_help) elif opt in ('-V', '--version'): # Display version. println("cjavapy:", BOLD) println(" version: {}".format(__version__)) if head is not None: println(" branch: {}\n commit: {}".format(*head)) else: println(" branch: {}\n commit: {}".format("(stable)", "(tag v{})".format(__version__))) println(" platform: {}".format(platform.platform())) println(" python: {}".format(sys.version.split('\n')[0])) elif opt in ('-g', '--gui'): # Run using GUI. conf['gui'] = True elif opt in ('-f', '--force'): # Force download. conf['force'] = True elif opt in ('-l', '--playlist', '--playlists'): conf['playlist'] = True if args: if 'gui' in conf and conf['gui']: # Enter GUI mode. from .gui import gui_main gui_main(*args, **conf) else: # Enter console mode. from .console import console_main console_main(*args, **conf) if __name__ == '__main__': main()