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


当前回答

使用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)

这就是:2行代码加上你的doc字符串,这是必要的,你可以解析你的参数,并在arguments对象中可用。

使用python-fire

自2017年以来,有另一个很酷的模块叫做蟒火。它可以为您的代码生成一个CLI界面,您可以进行零参数解析。下面是文档中的一个简单示例(这个小程序将函数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

其他回答

这是一个方法,而不是一个库,这似乎对我有用。

这里的目标是简洁,每个参数由一行解析,参数为可读性排列,代码简单且不依赖于任何特殊模块(仅os + sys),优雅地警告丢失或未知参数,使用简单的for/range()循环,并在python 2中工作。X和3.x

显示了两个切换标志(-d, -v)和两个由参数控制的值(-i xxx和-o xxx)。

import os,sys

def HelpAndExit():
    print("<<your help output goes here>>")
    sys.exit(1)

def Fatal(msg):
    sys.stderr.write("%s: %s\n" % (os.path.basename(sys.argv[0]), msg))
    sys.exit(1)

def NextArg(i):
    '''Return the next command line argument (if there is one)'''
    if ((i+1) >= len(sys.argv)):
        Fatal("'%s' expected an argument" % sys.argv[i])
    return(1, sys.argv[i+1])

### MAIN
if __name__=='__main__':

    verbose = 0
    debug   = 0
    infile  = "infile"
    outfile = "outfile"

    # Parse command line
    skip = 0
    for i in range(1, len(sys.argv)):
        if not skip:
            if   sys.argv[i][:2] == "-d": debug ^= 1
            elif sys.argv[i][:2] == "-v": verbose ^= 1
            elif sys.argv[i][:2] == "-i": (skip,infile)  = NextArg(i)
            elif sys.argv[i][:2] == "-o": (skip,outfile) = NextArg(i)
            elif sys.argv[i][:2] == "-h": HelpAndExit()
            elif sys.argv[i][:1] == "-":  Fatal("'%s' unknown argument" % sys.argv[i])
            else:                         Fatal("'%s' unexpected" % sys.argv[i])
        else: skip = 0

    print("%d,%d,%s,%s" % (debug,verbose,infile,outfile))

NextArg()的目标是在检查丢失的数据时返回下一个参数,而'skip'在使用NextArg()时跳过循环,将标志解析保持在一行内。

使用标准库附带的optparse。例如:

#!/usr/bin/env python
import optparse

def main():
  p = optparse.OptionParser()
  p.add_option('--person', '-p', default="world")
  options, arguments = p.parse_args()
  print 'Hello %s' % options.person

if __name__ == '__main__':
  main()

来源:使用Python创建UNIX命令行工具

然而,从Python 2.7开始,optparse已弃用,请参阅:为什么使用argparse而不是optparse?

由于这些原因,新的流行方法是argparse。Argparse > optparse > getopt

更新:从py2.7开始,argparse是标准库的一部分,optparse已弃用。

我更喜欢点击。它抽象了管理选项,并允许“(…)以一种可组合的方式,用尽可能少的代码创建漂亮的命令行界面”。

下面是用法示例:

import click

@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',
              help='The person to greet.')
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello %s!' % name)

if __name__ == '__main__':
    hello()

它还会自动生成格式良好的帮助页面:

$ python hello.py --help
Usage: hello.py [OPTIONS]

  Simple program that greets NAME for a total of COUNT times.

Options:
  --count INTEGER  Number of greetings.
  --name TEXT      The person to greet.
  --help           Show this message and exit.

我认为大型项目的最佳方法是optparse,但如果您正在寻找一种简单的方法,也许http://werkzeug.pocoo.org/documentation/script适合您。

from werkzeug import script

# actions go here
def action_foo(name=""):
    """action foo does foo"""
    pass

def action_bar(id=0, title="default title"):
    """action bar does bar"""
    pass

if __name__ == '__main__':
    script.run()

所以基本上每个函数action_*都暴露在命令行和一个nice 免费生成帮助信息。

python foo.py 
usage: foo.py <action> [<options>]
       foo.py --help

actions:
  bar:
    action bar does bar

    --id                          integer   0
    --title                       string    default title

  foo:
    action foo does foo

    --name                        string