在Python脚本中解析命令行参数(getopt问题)

4 投票
3 回答
6158 浏览
提问于 2025-04-16 05:29

有没有人能看出为什么下面这个脚本没有打印出传入的参数呢?

import sys, getopt

def usage():
    print 'Unknown arguments'

def main(argv):
    try:
        opts, args = getopt.getopt(argv,'fdmse:d',['files=','data-source=','mode=','start','end'])

    except getopt.GetoptError:
        usage()
        sys.exit(999)

    for opt, arg in opts:
        # print opt,arg 
        if opt in('-f','--files'):
            print 'files: ', arg  #

if __name__ == "__main__":
    main(sys.argv[1:])

当我在命令行运行这个脚本,并传入参数 -f=dummy.csv 时,似乎调用的是 usage() 函数 - 这是为什么呢?

顺便说一下,我觉得这个程序的逻辑有点奇怪(我从 这里 复制的)。我本来以为逻辑应该先在 try 部分实现,然后再是异常处理部分。

这样写(如上面的代码所示)算不算是“Pythonic”的写法呢?

3 个回答

0

导入并使用argparse,而不是getopt。argparse使用起来简单多了,而且几乎包含了你从命令行运行所需的所有功能。

举个例子,

    parser = argparse.ArgumentParser(
        description='Description of what the module does when run.')
    parser.add_argument("-o", "--output", help='Path of log file.')
    args = parser.parse_args()

就这么简单。不过,当然你需要在文件的顶部导入argparse,这样它才能正常工作。

2

你找到答案了吗?

调试Python错误的一种方法是把代码从try块中移出来(或者暂时复制出来用于调试)。这样你就能看到完整的错误追踪信息。

当然,另一种方法是简化测试案例。在这里,我把问题简化成了三行代码,并尝试了@s.lott提到的解决方案(在getopts调用中使用'f:'),最后还展示了用不同测试数据调用时的表现:

$ cat x1.py
import sys, getopt
opts, args = getopt.getopt(sys.argv[1:],'fdmse:d',['files=','data-source=','mode=','start','end'])
print "opts=", opts, "args=", args

$ python x1.py -f=dummy.csv argblah
Traceback (most recent call last):
  File "x1.py", line 2, in <module>
    opts, args = getopt.getopt(sys.argv[1:],'fdmse:d',['files=','data-source=','mode=','start','end'])
  File "/usr/lib/python2.6/getopt.py", line 91, in getopt
    opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
  File "/usr/lib/python2.6/getopt.py", line 191, in do_shorts
    if short_has_arg(opt, shortopts):
  File "/usr/lib/python2.6/getopt.py", line 207, in short_has_arg
    raise GetoptError('option -%s not recognized' % opt, opt)
getopt.GetoptError: option -= not recognized

$ sed 's/fdm/f:dm/' <x1.py >x2.py

$ diff x1.py x2.py
2c2
< opts, args = getopt.getopt(sys.argv[1:],'fdmse:d',['files=','data-source=','mode=','start','end'])
---
> opts, args = getopt.getopt(sys.argv[1:],'f:dmse:d',['files=','data-source=','mode=','start','end'])

$ python x2.py -f=dummy.csv argblah
opts= [('-f', '=dummy.csv')] args= ['argblah']

$ python x1.py -f dummy.csv argblah
opts= [('-f', '')] args= ['dummy.csv', 'argblah']
1

通常,我会认为逻辑会在try分支中实现。

“通常”?这是什么意思呢?

这个程序应该做什么?哪些异常是合理的?程序在遇到异常时会怎么处理。

其实没有“通常”这种说法。就像没有什么是正常的赋值语句或正常的函数定义一样。

你的程序应该做的是为了达到预期的结果而合理的操作。没有“通常”这种概念。

撰写回答