15.3. getopt — 解析命令行参数
目的:命令行选项语法解析
getopt
模块是原始的命令行选项语法解析器,它支持所有由Unix函数 getopt
建立的惯例。它能解析一串参数序列,例如 sys.argv
并返回包含(选项,参数)对的元组和非选项参数的序列。
可支持的选项语法包括长和短两种形式的选项:
-a
-bval
-b val
--noarg
--witharg=val
--witharg val
注释
getopt
并没有被弃用,但是argparse
的维护更加活跃,应当被用于新的开发项目上。
函数参数
getopt()
函数有以下三个参数:
- 第一个参数是被解析的序列。它通常来自于
sys.argv[1:]
(忽略了位于sys.arg[0]
位置上的程序名)。 - 第二个参数是对单字符选项的定义字符串。如果其中一个选项需要参数,其代表字符后会有一个冒号。
- 第三个参数,如果用到的话,则是长类型选项名序列。长类型选项往往多于一个字符表示,如
--noarg
或--witharg
。在该序列内的选项名应当不包括--
前缀。如果长选项需要后跟参数,选项名后将有一个=
后缀。
长和短形式的选项将在单次调用后被合并。
短选项
此示例程序接受三个选项。-a
是一个普通的标识符,而 -b
和 -c
需要一个参数。选项定义字符串为 "ab:c:"
。
- 在选项定义字符串中,不需要前导符号
-
; - 需要参数的选项,在选项定义字符串后需要添加后缀
:
。
getopt_short.py
import getopt
opts, args = getopt.getopt(['-a', '-bval', '-c', 'val'], 'ab:c:')
for opt in opts:
print(opt)
此程序传递一个模拟的选项值列表给 getopt()
函数来展示它是如何处理的。以下为结果:
- 上例中的
opts
变量接受了一个返回的列表; opts
中的每一个元素都是(选项, 参数)
形式的元组。args
参数本应接受一个由处理后剩余的参数组成的列表,本例中则为一个空列表。
$ python3 getopt_short.py
('-a', '')
('-b', 'val')
('-c', 'val')
长选项格式
对于具有两个选项 --noarg
和 --witharg
的程序,长选项定义语句应该为 [ 'noarg', 'witharg=' ]
。
- 无参数选项定义字符串不需带有前导符号
--
- 需要参数的长选项,在定义时需要跟后缀等号
=
getopt_long.py
import getopt
opts, args = getopt.getopt(
['--noarg', # 无参数选项
'--witharg', 'val', # 带参数选项
'--witharg2=another'], # 也可用等号连接选项与参数
'',
['noarg', 'witharg=', 'witharg2='],
)
for opt in opts:
print(opt)
因为此示例中没有使用短格式的选项,因此 getopt()
函数的第二个返回值 args
为空。
$ python3 getopt_long.py
('--noarg', '')
('--witharg', 'val')
('--witharg2', 'another')
一个完整的例子
此示例是一个更加完整的程序,它带有五个选项:-o
,-v
,--output
,--verbose
,--version
。
-o
,--output
,和 --version
都需要一个参数。
getopt_example.py
import getopt
import sys
version = '1.0'
verbose = False
output_filename = 'default.out'
print('ARGV :', sys.argv[1:])
try:
options, remainder = getopt.getopt(
# 这里将解析后的选项-参数对存入变量 options 了,勿与后文的 opt,arg 混淆
sys.argv[1:],
'o:v',
['output=',
'verbose',
'version=',
])
except getopt.GetoptError as err:
print('ERROR:', err)
sys.exit(1)
print('OPTIONS :', options)
for opt, arg in options:
# arg 是此选项对应的参数, 不要与上文的 remainder 混淆
if opt in ('-o', '--output'):
output_filename = arg
elif opt in ('-v', '--verbose'):
verbose = True
elif opt == '--version':
version = arg
print('VERSION :', version)
print('VERBOSE :', verbose)
print('OUTPUT :', output_filename)
print('REMAINING :', remainder)
此程序可以通过多种方式被调用。当不带参数地调用它时, 将会使用默认的设置。
$ python3 getopt_example.py
ARGV : []
OPTIONS : []
VERSION : 1.0
VERBOSE : False
OUTPUT : default.out
REMAINING : []
一个单字符选项与它的参数可以用空格分隔。
$ python3 getopt_example.py -o foo
ARGV : ['-o', 'foo'] # 用空格分隔的 选项 参数
OPTIONS : [('-o', 'foo')]
VERSION : 1.0
VERBOSE : False
OUTPUT : foo
REMAINING : []
或者, 可以直接将单字符选项与其参数组合。
$ python3 getopt_example.py -ofoo
ARGV : ['-ofoo'] # 直接连写的 选项参数
OPTIONS : [('-o', 'foo')] # 依然成功解析
VERSION : 1.0
VERBOSE : False
OUTPUT : foo
REMAINING : []
一个长格式的选项也可以用空格分隔其参数。
$ python3 getopt_example.py --output foo
ARGV : ['--output', 'foo']
OPTIONS : [('--output', 'foo')]
VERSION : 1.0
VERBOSE : False
OUTPUT : foo
REMAINING : []
但当要组合一个长格式选项与其参数时,应当使用等号 =
分隔。
$ python3 getopt_example.py --output=foo
ARGV : ['--output=foo']
OPTIONS : [('--output', 'foo')]
VERSION : 1.0
VERBOSE : False
OUTPUT : foo
REMAINING : []
缩写长格式选项
只要提供了唯一的前缀,长格式选项不必在命令行上完整地拼出。
$ python3 getopt_example.py --o foo # 这里可不是 -o 哦
ARGV : ['--o', 'foo']
OPTIONS : [('--output', 'foo')]
VERSION : 1.0
VERBOSE : False
OUTPUT : foo
REMAINING : []
如果提供地前缀并不唯一,则会抛出异常。
$ python3 getopt_example.py --ver 2.0
# --version 与 --verbose 混淆
ARGV : ['--ver', '2.0']
ERROR: option --ver not a unique prefix
GNU 风格的选项解析
通常地,一旦遇到第一个非选项参数,选项处理就会停止。
$ python3 getopt_example.py -v not_an_option --output foo
ARGV : ['-v', 'not_an_option', '--output', 'foo']
OPTIONS : [('-v', '')]
VERSION : 1.0
VERBOSE : True
OUTPUT : default.out
REMAINING : ['not_an_option', '--output', 'foo']
为了在命令行以任意顺序混合选项与非选项,使用 gnu_getopt()
来代替 getopt()
。
getopt_gnu.py
import getopt
import sys
version = '1.0'
verbose = False
output_filename = 'default.out'
print('ARGV :', sys.argv[1:])
try:
options, remainder = getopt.gnu_getopt(
sys.argv[1:],
'o:v',
['output=',
'verbose',
'version=',
])
except getopt.GetoptError as err:
print('ERROR:', err)
sys.exit(1)
print('OPTIONS :', options)
for opt, arg in options:
if opt in ('-o', '--output'):
output_filename = arg
elif opt in ('-v', '--verbose'):
verbose = True
elif opt == '--version':
version = arg
print('VERSION :', version)
print('VERBOSE :', verbose)
print('OUTPUT :', output_filename)
print('REMAINING :', remainder)
在上一个示例中更改了函数调用后,两者的差异变得清楚了。
$ python3 getopt_gnu.py -v not_an_option --output foo
ARGV : ['-v', 'not_an_option', '--output', 'foo']
OPTIONS : [('-v', ''), ('--output', 'foo')]
VERSION : 1.0
VERBOSE : True
OUTPUT : foo
REMAINING : ['not_an_option']
结束参数处理
如果 getopt()
在输入的参数中遇到 "--
",它将停止将剩余的参数作为选项处理。此特性可用来传递格式上类似于选项的参数,例如以 -
符号开头的文件名。
$ python3 getopt_example.py -v -- --output foo
ARGV : ['-v', '--', '--output', 'foo']
OPTIONS : [('-v', '')] # -- 本身不作为参数传递
VERSION : 1.0
VERBOSE : True
OUTPUT : default.out
REMAINING : ['--output', 'foo']
# 之后的参数都将存入 getopt() 的第二个返回值
参阅
- Standard library documentation for getopt
argparse
-- 在更新的应用中,用argparse
模块代替getopt
。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。