理解 OptionParser

12 投票
3 回答
67385 浏览
提问于 2025-04-16 11:35

我在尝试使用 optparse,这是我最初写的脚本。

#!/usr/bin/env python

import os, sys
from optparse import OptionParser

parser = OptionParser()
usage = "usage: %prog [options] arg1 arg2"

parser.add_option("-d", "--dir", type="string",
                  help="List of directory",
                  dest="inDir", default=".")

parser.add_option("-m", "--month", type="int",
                  help="Numeric value of the month", 
                  dest="mon")

options, arguments = parser.parse_args()

if options.inDir:
    print os.listdir(options.inDir)

if options.mon:
    print options.mon

def no_opt()
    print "No option has been given!!"

现在,我想实现以下功能:

  1. 如果没有给选项提供参数,它会使用“默认”值。比如说,myScript.py -d 会列出当前目录,或者 -m 如果没有参数,就会用当前月份作为参数。
  2. 对于“--month”选项,只允许输入01到12之间的数字作为参数。
  3. 想要组合多个选项来执行不同的任务,比如 myScript.py -d this_dir -m 02 会和单独使用 -d 或 -m 时的效果不同。
  4. 只有在没有提供任何选项时,才会打印出 "没有提供选项!!"。

这些功能可以实现吗?我去过 doc.python.org 网站寻找答案,但作为一个初学者,我在那些页面里迷失了。非常感谢你的帮助,提前谢谢你。祝好!!


更新:16/01/11

我觉得我还是缺少了一些东西。这是我现在脚本里的内容。

parser = OptionParser()
usage = "usage: %prog [options] arg1 arg2"

parser.add_option("-m", "--month", type="string",
                  help="select month from  01|02|...|12",
                  dest="mon", default=strftime("%m"))

parser.add_option("-v", "--vo", type="string",
                  help="select one of the supported VOs",
                  dest="vos")

options, arguments = parser.parse_args()

这是我的目标:

  1. 不带任何选项运行脚本,返回 option.mon [正常工作]
  2. 带 -m 选项运行脚本,返回 option.mon [正常工作]
  3. 仅带 -v 选项运行脚本,只返回 option.vos [完全不工作]
  4. 带 -m 和 -v 选项运行脚本,会做不同的事情 [还没达到目标]

当我只用 -m 选项运行脚本时,它先打印 option.mon,然后打印 option.vos,这是我不想要的。如果有人能给我指个方向,我会非常感激。祝好!!


第三次更新

    #!/bin/env python

    from time import strftime
    from calendar import month_abbr
    from optparse import OptionParser

    # Set the CL options 
    parser = OptionParser()
    usage = "usage: %prog [options] arg1 arg2"

    parser.add_option("-m", "--month", type="string",
                      help="select month from  01|02|...|12", 
              dest="mon", default=strftime("%m"))

    parser.add_option("-u", "--user", type="string",
                      help="name of the user", 
              dest="vos")

    options, arguments = parser.parse_args()

    abbrMonth = tuple(month_abbr)[int(options.mon)]

    if options.mon:
        print "The month is: %s" % abbrMonth 

    if options.vos:
        print "My name is: %s" % options.vos 

    if options.mon and options.vos:
        print "I'm '%s' and this month is '%s'" % (options.vos,abbrMonth)

这是脚本在不同选项下运行时的返回结果:

# ./test.py
The month is: Feb
#
# ./test.py -m 12
The month is: Dec
#
# ./test.py -m 3 -u Mac
The month is: Mar
My name is: Mac
I'm 'Mac' and this month is 'Mar'
#
# ./test.py -u Mac
The month is: Feb
My name is: Mac
I'm 'Mac' and this month is 'Feb'

我只想看到:

 1. `I'm 'Mac' and this month is 'Mar'` - as *result #3*  
 2. `My name is: Mac` - as *result #4*

我哪里做错了?祝好!!


第四次更新:

我自己回答自己:这样我可以得到我想要的结果,但我还是不太满意。

#!/bin/env python

import os, sys
from time import strftime
from calendar import month_abbr
from optparse import OptionParser

def abbrMonth(m):
    mn = tuple(month_abbr)[int(m)]
    return mn

# Set the CL options 
parser = OptionParser()
usage = "usage: %prog [options] arg1 arg2"

parser.add_option("-m", "--month", type="string",
                  help="select month from  01|02|...|12",
                  dest="mon")

parser.add_option("-u", "--user", type="string",
                  help="name of the user",
                  dest="vos")

(options, args) = parser.parse_args()

if options.mon and options.vos:
    thisMonth = abbrMonth(options.mon)
    print "I'm '%s' and this month is '%s'" % (options.vos, thisMonth)
    sys.exit(0)

if not options.mon and not options.vos:
    options.mon = strftime("%m")

if options.mon:
    thisMonth = abbrMonth(options.mon)
    print "The month is: %s" % thisMonth

if options.vos:
    print "My name is: %s" % options.vos

现在这段代码给了我正好想要的结果:

# ./test.py 
The month is: Feb

# ./test.py -m 09
The month is: Sep

# ./test.py -u Mac
My name is: Mac

# ./test.py -m 3 -u Mac
I'm 'Mac' and this month is 'Mar'

这真的是唯一的方法吗?对我来说看起来并不是“最佳方式”。祝好!!

3 个回答

1

这里是用来说明 argparse.ArgumentParser 的 add_argument() 方法中可选项的选择。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
from argparse import ArgumentParser
from datetime import date

parser = ArgumentParser()

parser.add_argument("-u", "--user", default="Max Power", help="Username")
parser.add_argument("-m", "--month", default="{:02d}".format(date.today().month),
                    choices=["01","02","03","04","05","06",
                             "07","08","09","10","11","12"],
                    help="Numeric value of the month")

try:
    args = parser.parse_args()
except:
    parser.error("Invalid Month.")
    sys.exit(0) 

print  "The month is {} and the User is {}".format(args.month, args.user)
2

你的解决方案在我看来是合理的。以下是一些评论:

  • 我不明白你为什么要把 month_abbr 转换成一个元组;其实不使用 tuple() 也能正常工作。
  • 我建议你检查一下输入的月份值是否有效(如果发现问题,可以使用 raise OptionValueError 来抛出错误)。
  • 如果你真的希望用户输入的月份格式是“01”、“02”……或者“12”,你可以使用“choice”这个选项类型;具体可以参考 选项类型的文档
3

optparse这个库已经不再推荐使用了;你应该在Python2和Python3中都使用argparse

http://docs.python.org/library/argparse.html#module-argparse

撰写回答