解析命令行参数的最佳方法是什么?

360 投票
15 回答
374143 浏览
提问于 2025-04-10 23:04

什么是解析Python命令行参数最简单、最简洁、以及最灵活的方法或库呢?

15 个回答

96

使用 docopt

自2012年以来,有一个非常简单、强大而且真的很 的模块,用于处理命令行参数,叫做 docopt。下面是它文档中的一个例子:

"""Naval Fate.

Usage:
  naval_fate.py ship new <name>...
  naval_fate.py ship <name> move <x> <y> [--speed=<kn>]
  naval_fate.py ship shoot <x> <y>
  naval_fate.py mine (set|remove) <x> <y> [--moored | --drifting]
  naval_fate.py (-h | --help)
  naval_fate.py --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.

"""
from docopt import docopt


if __name__ == '__main__':
    arguments = docopt(__doc__, version='Naval Fate 2.0')
    print(arguments)

就这样:只需要两行代码加上你的文档字符串,这个文档字符串是 必不可少 的,你就能解析参数,并且在你的参数对象中使用它们。

使用 python-fire

自2017年以来,还有另一个很酷的模块,叫做 python-fire。它可以为你的代码生成一个命令行界面,而你根本不需要处理参数解析。下面是文档中的一个简单例子(这个小程序将 double 函数暴露到命令行):

import fire

class Calculator(object):

  def double(self, number):
    return 2 * number

if __name__ == '__main__':
  fire.Fire(Calculator)

你可以在命令行中运行:

> calculator.py double 10
20
> calculator.py double --number=15
30
433

argparse 是一个很实用的工具。下面是它的简单使用步骤:

1) 初始化

import argparse

# Instantiate the parser
parser = argparse.ArgumentParser(description='Optional app description')

2) 添加参数

# Required positional argument
parser.add_argument('pos_arg', type=int,
                    help='A required integer positional argument')

# Optional positional argument
parser.add_argument('opt_pos_arg', type=int, nargs='?',
                    help='An optional integer positional argument')

# Optional argument
parser.add_argument('--opt_arg', type=int,
                    help='An optional integer argument')

# Switch
parser.add_argument('--switch', action='store_true',
                    help='A boolean switch')

3) 解析

args = parser.parse_args()

4) 访问

print("Argument values:")
print(args.pos_arg)
print(args.opt_pos_arg)
print(args.opt_arg)
print(args.switch)

5) 检查值

if args.pos_arg > 10:
    parser.error("pos_arg cannot be larger than 10")

使用方法

正确使用:

$ ./app 1 2 --opt_arg 3 --switch

Argument values:
1
2
3
True

错误参数:

$ ./app foo 2 --opt_arg 3 --switch
usage: convert [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg]
app: error: argument pos_arg: invalid int value: 'foo'

$ ./app 11 2 --opt_arg 3
Argument values:
11
2
3
False
usage: app [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg]
convert: error: pos_arg cannot be larger than 10

完整帮助:

$ ./app -h

usage: app [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg]

Optional app description

positional arguments:
  pos_arg            A required integer positional argument
  opt_pos_arg        An optional integer positional argument

optional arguments:
  -h, --help         show this help message and exit
  --opt_arg OPT_ARG  An optional integer argument
  --switch           A boolean switch
211

这个回答提到的 optparse 适合旧版本的 Python。对于 Python 2.7 及以上版本,argparse 替代了 optparse。想了解更多信息,可以查看 这个回答

正如其他人所指出的,使用 optparse 比 getopt 更好。getopt 基本上是 C 语言标准库函数 getopt(3) 的直接映射,使用起来不太方便。

虽然 optparse 的写法稍微多一些,但它的结构更清晰,后续扩展也更简单。

下面是一行典型的代码,用来给你的解析器添加一个选项:

parser.add_option('-q', '--query',
            action="store", dest="query",
            help="query string", default="spam")

这行代码基本上是自解释的;在处理时,它会接受 -q 或 --query 作为选项,把传入的参数存储在一个叫做 query 的属性里,如果你没有指定,它还有一个默认值。它也很方便,因为你可以在定义选项时直接声明帮助信息(当用 -h/--help 运行时会用到)。

通常你会用以下代码来解析你的参数:

options, args = parser.parse_args()

这段代码默认会解析传递给脚本的标准参数 (sys.argv[1:])。

然后,options.query 会被设置为你传给脚本的值。

你只需这样创建一个解析器:

parser = optparse.OptionParser()

这些都是你需要的基本知识。下面是一个完整的 Python 脚本,展示了这些内容:

import optparse

parser = optparse.OptionParser()

parser.add_option('-q', '--query',
    action="store", dest="query",
    help="query string", default="spam")

options, args = parser.parse_args()

print 'Query string:', options.query

这段代码只有 5 行,展示了基础用法。

把它保存为 sample.py,然后用以下命令运行一次:

python sample.py

再用以下命令运行一次:

python sample.py --query myquery

除此之外,你会发现 optparse 非常容易扩展。在我的一个项目中,我创建了一个 Command 类,可以轻松地在命令树中嵌套子命令。它大量使用 optparse 来连接命令。虽然我不能在几行内简单解释,但你可以随意 浏览我的代码库,查看主要类,以及 一个使用它和选项解析器的类

撰写回答